﻿using AudioStudio;
using AudioStudio.Components;
using com.yoozoo.gta.Extension;
using com.youzu.got.protocol;
using DG.Tweening;
using System;
using System.Collections;
using System.Collections.Generic;
using com.yoozoo.gta.Extension.UGUI.ScreenOrientationEx;
using com.yoozoo.gta.Gameplay.RTS;
using com.youzu.warh.protocol;
using Gameplay.PVE.Utils;
using Unity.Profiling;
using UnityEngine;
using WorldMapBase.Tile.Pool;
using XLua;
using Yoozoo.Framework.Managers;
using Yoozoo.Gameplay.RTS.Proto;
using Yoozoo.Gta.Common;
using Yoozoo.Managers;
using Yoozoo.Mars.Got;
using Yoozoo.UI.YGUI;
using Coordinate = Yoozoo.Gameplay.RTS.Proto.Coordinate;
using MarchStatus = Yoozoo.Gameplay.RTS.Proto.MarchStatus;
using TargetCoordinateType = Yoozoo.Gameplay.RTS.Proto.TargetCoordinateType;
using Random = UnityEngine.Random;

namespace Yoozoo.Gameplay.RTS
{

    // 管理部队，Lua中marchManager的作用
    // 并且会合并一些RTSTest中的功能，如Update()中执行MarchEntity.Update()
    [CSharpCallLua]
    public delegate void UpdateSoldierCallBack(UpdateSoldierStruct p);
    public class MarchManager
    {
        public static UpdateSoldierCallBack UpdateSoldierCallBack;
        public LuaFunction ParseSiegeFightInfo;
        public LuaFunction DispatchSkillEvent;
        public LuaFunction FocusTroopAction;
        private LuaFunction IsMyAlliance;
        #region Profiler标记
        
//        private static ProfilerMarker k_UpdateTroopMarchBaseInfo = new ProfilerMarker("MarchManager.UpdateTroopMarchBaseInfo");
//        private static ProfilerMarker k_UpdateTroopMarchBaseInfo2 = new ProfilerMarker("MarchManager.UpdateTroopMarchBaseInfo2");
//        private static ProfilerMarker k_UpdateTroopMarchBaseInfo3 = new ProfilerMarker("MarchManager.UpdateTroopMarchBaseInfo3");
        private static ProfilerMarker k_MarchBesiegeManager = new ProfilerMarker("MarchManager.UpdateMarchBesiegeManager");
//        private static ProfilerMarker k_UpdateTroopMarchInfo1 = new ProfilerMarker("MarchManager.UpdateTroopMarchInfo1");
//        private static ProfilerMarker k_UpdateTroopMarchInfo2 = new ProfilerMarker("MarchManager.UpdateTroopMarchInfo2");
//        private static ProfilerMarker k_UpdateTroopMarchInfo3 = new ProfilerMarker("MarchManager.UpdateTroopMarchInfo3");
//        private static ProfilerMarker k_UpdateTroopMarchInfo4 = new ProfilerMarker("MarchManager.UpdateTroopMarchInfo4");
//        private static ProfilerMarker k_UpdateTroopMarchInfo5 = new ProfilerMarker("MarchManager.UpdateTroopMarchInfo5");
//        private static ProfilerMarker k_UpdateTroopMarchInfo6 = new ProfilerMarker("MarchManager.UpdateTroopMarchInfo6");
//        private static ProfilerMarker k_UpdateTroopMarchInfo7 = new ProfilerMarker("MarchManager.UpdateTroopMarchInfo7");
        private static ProfilerMarker k_CreateMarchProfilerMarker = new ProfilerMarker("MarchManager.CreateMarch");
        private static ProfilerMarker k_CreateMarchInitializeProfilerMarker = new ProfilerMarker("MarchManager.CreateMarch.Initialize");
        private static ProfilerMarker k_DestroyMarch = new ProfilerMarker("MarchManager.DestroyMarch");
        private static ProfilerMarker k_UpdateTroopMarchInfo = new ProfilerMarker("MarchManager.UpdateTroopMarchInfo");
        private static ProfilerMarker k_UpdateMonsterBaseInfo = new ProfilerMarker("MarchManager.UpdateMonsterBaseInfo");
        private static ProfilerMarker k_UpdateMonsterInfo = new ProfilerMarker("MarchManager.UpdateMonsterInfo");
        private static ProfilerMarker k_UpdateMonsterInfo1 = new ProfilerMarker("MarchManager.UpdateMonsterInfo1");
        private static ProfilerMarker k_UpdateMonsterInfo2 = new ProfilerMarker("MarchManager.UpdateMonsterInfo2");
        private static ProfilerMarker k_UpdateMonsterInfo3 = new ProfilerMarker("MarchManager.UpdateMonsterInfo3");
        private static ProfilerMarker k_UpdateMonsterInfo4 = new ProfilerMarker("MarchManager.UpdateMonsterInfo4");
        private static ProfilerMarker k_UpdateMonsterInfo5 = new ProfilerMarker("MarchManager.UpdateMonsterInfo5");
        private static ProfilerMarker k_UpdateMonsterInfo6 = new ProfilerMarker("MarchManager.UpdateMonsterInfo6");
        private static ProfilerMarker k_PlayerBattleSound = new ProfilerMarker("MarchManager.PlayerBattleSound");
        private static ProfilerMarker k_UpdateLod = new ProfilerMarker("MarchManager.Update.UpdateLod");
        private static ProfilerMarker k_marchLine = new ProfilerMarker("MarchManager.Update.marchLine");
        private static ProfilerMarker k_marchState = new ProfilerMarker("MarchManager.Update.marchState");
        private static ProfilerMarker k_SquareChildHideCount = new ProfilerMarker("MarchManager.Update.SquareChildHideCount");
        private static ProfilerMarker k_entiryUpdate = new ProfilerMarker("MarchManager.Update.entiryUpdate");
        private static ProfilerMarker k_changeHud = new ProfilerMarker("MarchManager.Update.changeHud");
        private static ProfilerMarker k_changePos = new ProfilerMarker("MarchManager.Update.changePos");
        private static ProfilerMarker k_handlermarchshadow = new ProfilerMarker("MarchManager.Update.handlermarchshadow");
        private static ProfilerMarker k_updateForce = new ProfilerMarker("MarchManager.Update.updateForce");
        private static ProfilerMarker k_SquareDataManager = new ProfilerMarker("MarchManager.Update.SquareDataManager");
        private static ProfilerMarker k_RoundFightHelper = new ProfilerMarker("MarchManager.Update.RoundFightHelper");
        public const int MaxTroop = 1200;
        public const int MarchEntityPoolNum = 0;
        public const int MonsterEntityPoolNum = 0;
        public static MarchManager Instance;
        private static int _currentMarchNum;
        private ListPool<Troop> _listPool;
        public static int CurrentMarchNum
        {
            get
            {
                return _currentMarchNum;
            } 
            set
            {
                _currentMarchNum = value;
                RTSQualityHelper.OnMarchNumChanged(_currentMarchNum);
            }
        }
        #endregion

        #region 变量声明 
        
//        private readonly Dictionary<long, int> itemKeyAndIndexMap = new Dictionary<long, int>();
//        private readonly Dictionary<long, long> assemblyIdKeyAndMarchIdMap = new Dictionary<long, long>();
//        private readonly Dictionary<long, long> marchIdKeyAndassemblyIdMap = new Dictionary<long, long>();

        private readonly Dictionary<TargetCoordinateType, Dictionary<long, int>> rtsEntityDictionary =
            new Dictionary<TargetCoordinateType, Dictionary<long, int>>();
        private readonly List<MarchEntity> marchEnitiesBase = new List<MarchEntity>(MarchEntityPoolNum);
        
        private readonly List<MarchEntity> marchEntityPool = new List<MarchEntity>(MarchEntityPoolNum);
        private readonly List<MarchEntity> monsterEntityPool = new List<MarchEntity>(MonsterEntityPoolNum);

        private readonly List<TroopPath> paths = new List<TroopPath>(MarchEntityPoolNum);
        private readonly List<MarchEntity> updateChaseList = new List<MarchEntity>();
        private readonly List<MarchEntity> updateChaseAttackerList = new List<MarchEntity>();
        private readonly Dictionary<Troop,List<Troop>> targetIdAndSourceIdMap = new Dictionary<Troop, List<Troop>>();
        private readonly Segment[] segments = new Segment[MaxTroop];

        private long _FocusTroopId;
        private TargetCoordinateType _FocusTroopType;
        private float _FocusLerpTime;
        private float _FocusLerpStartTime;
        private Vector2 _FocusStartPosition;
        private int count;
        public int Count => count;
        private int waitDeleteCount = 0;
        public bool drawLodInfo = true;
        private LuaFunction L_BindHudToMarchDataFunc;
        private Transform mainCameraTransform;
        public MarchContext marchContext = new MarchContext();
        private Dictionary<long, long> marchToPlayer = new Dictionary<long, long>(128);
        private PlayerBattle playerBattle;

        private Dictionary<long, PlayerBattleList> playerToMarch = new Dictionary<long, PlayerBattleList>(MarchManager.MarchEntityPoolNum);

        private List<MarchEntity> _waitDeleteEntityList = new List<MarchEntity>();

        private HudLodScaleConfig _hudConfig;
        private TargetCoordinateType oldTargetType;
        
        private float _lastClientTime;
        internal string allianceCode;

        private Transform marchEntityRoot;
        private Transform monsterEntityRoot;
        private Transform SelectedObjRoot;


        private bool spriteUpdateEnabled = true;
        [BlackList]
        public static int BattleTroopCount = 0;

        public MarchAudioController audioController;

        //部队移动的音频计数
        public int moveAudioCount = 0;
        //部队移动的音频最多(包含虚拟音频)
        public static int moveAudioCountLimit = 20;
        #endregion

        private RoundFightPlayer _roundFightPlayer;
        private RTSResourceManager _rtsResMgr;

        private CanvasGroup _marchCanvasGroup;
        private CanvasGroup _monsterCanvasGroup;
        private float tweenAlphaTime = 0.4f;

        public bool IsInArena = false;
        private LuaFunction eventLua;

        private class DeadEffect
        {
            public float startTime;
            public GameObject effect;
        }
        private List<DeadEffect> deadEffectList = new List<DeadEffect>(16);

        private long sandBoxServerId = 0;// 当前视野服务器id >0 为有效值 

        private long userServerId = 0; // 当前用户服务器id >0 为有效值
        
        [BlackList]
        public MarchManager()
        {
            Instance = this;
            var worldCameraManager = WorldCameraManager.GetInstance();
            if (worldCameraManager)
            {
                var camera = worldCameraManager.GetCamera();
                if (camera)
                {
                    mainCameraTransform = WorldCameraManager.GetInstance().GetCamera().transform;
                }
            }
            playerBattle = new PlayerBattle(this);
            _hudConfig = new HudLodScaleConfig();
            _hudConfig.Init();
            SquareDataManager.Instance.Initialize();
            spriteUpdateEnabled = true;
            ///监听暂停相关逻辑
            GTAGameStart.AddLuaPauseEventHandler(PauseEventHandler);
            _rtsResMgr = ArmyManager.Instance.ResourceManager;

            _roundFightPlayer = new RoundFightPlayer();
            _roundFightPlayer.Init(this, _rtsResMgr);
            moveAudioCount = 0;

            audioController = new MarchAudioController();
            ClassManager.Store<TroopPath>(100);
            GTAGameStart.eventManager.AddEvent<com.youzu.warh.protocol.SCRoundFight>(ClientEvent.RoundFight,OnRoundFight);
            UpdateSoldierCallBack = LuaManager.mainState.Global.GetInPath<UpdateSoldierCallBack>("G_MarchManager.OnUpdateSoldierCallBack");

            ParseSiegeFightInfo = LuaManager.mainState.GetFunction("G_MarchManager.parseSiegeFightInfo");
            _listPool = new ListPool<Troop>(4,true,4,4,60);
            DispatchSkillEvent = LuaManager.mainState.GetFunction("G_MarchManager.dispatchSkillEvent");
            FocusTroopAction = LuaManager.mainState.GetFunction("L_SandBoxManager.FocusTroopAction");
            IsMyAlliance = LuaManager.mainState.GetFunction("CityLuaFunction.IsMyAlliance");
        }

        public void OnWorldCameraReady()
        {
            if (mainCameraTransform == null)
            {
                mainCameraTransform = WorldCameraManager.GetInstance().GetCamera().transform;
            }
        }
        
        public void OnRoundFightOver()
        {
            for (int i = 0; i < marchEnitiesBase.Count; i++)
            {
                var entity = marchEnitiesBase[i];
                entity.MarchInfo.SetIsJustLeaveBattle(false);
                entity.UpdateHudHpPercent();
            }
        }

        public void RegisterNonResourceReliableTasks()
        {
            var marchHudLayer = LayerMask.NameToLayer("MarchHud");
            
            FrameExecuteTimeMonitor.AddTask(() =>
            {
                var marchEntityObj = new GameObject("[MarchEntityPool]");
                marchEntityObj.AddComponent<Canvas>();
                _marchCanvasGroup = marchEntityObj.AddComponent<CanvasGroup>();
                marchEntityObj.layer = marchHudLayer;
                marchEntityRoot = marchEntityObj.transform;
                if (marchRootTransform && marchRootTransform.Valid())
                {
                    marchEntityRoot.SetParent(marchRootTransform);
                }
            });
            FrameExecuteTimeMonitor.AddTask(() =>
            {
                var monsterEntityObj = new GameObject("[MonsterEntityPool]");
                monsterEntityObj.AddComponent<Canvas>();
                monsterEntityRoot = monsterEntityObj.transform;
                _monsterCanvasGroup = monsterEntityObj.AddComponent<CanvasGroup>();
                monsterEntityObj.layer = marchHudLayer;
                if (marchRootTransform && marchRootTransform.Valid())
                {
                    monsterEntityRoot.SetParent(marchRootTransform);
                }
            });

            FrameExecuteTimeMonitor.AddTask(() =>
            {
                var SelectedObj = new GameObject("[SelectedObj]");
                SelectedObj.AddComponent<Canvas>();
                SelectedObj.AddComponent<CanvasGroup>();
                SelectedObjRoot = SelectedObj.transform;
                SelectedObj.layer = marchHudLayer;
                if (marchRootTransform && marchRootTransform.Valid())
                {
                    SelectedObjRoot.SetParent(marchRootTransform);
                }
            });
          
            
            marchEntityPool.Clear();
            for (int i = 0; i < MarchEntityPoolNum; i++)
            {
                FrameExecuteTimeMonitor.AddTask(() =>
                {
                    marchEntityPool.Add(CreateNewMarchEntity());
                });
            }
            monsterEntityPool.Clear();
            for (int i = 0; i < MonsterEntityPoolNum; i++)
            {
                FrameExecuteTimeMonitor.AddTask(() =>
                {
                    monsterEntityPool.Add(CreateNewMarchEntity(true));
                });
            }
        }

        private readonly string marchEntityObjName = "MarchEntityPoolObj";
        private readonly string monsterEntityObjName = "MonsterEntityPoolObj";

        private MarchEntity CreateNewMarchEntity(bool isMonster = false)
        {
            string name;
            if (isMonster)
            {
                name = monsterEntityObjName;
            }
            else
            {
                name = marchEntityObjName;
            }
            var gameObject = new GameObject(name);
            var marchEntity = new MarchEntity();
            var marchMono = gameObject.AddComponent<MarchMono>();
            marchEntity.Mono = marchMono;
            gameObject.transform.SetParent(isMonster == false ? marchEntityRoot: monsterEntityRoot);
            marchMono.enabled = false;
            return marchEntity;
        }
        

        private MarchEntity GetMarchEntityFromPool(bool isMonster = false)
        {
            MarchEntity entity;
            if (!isMonster)
            {
                if (marchEntityPool.Count == 0)
                {
                    entity = CreateNewMarchEntity();
                }
                else
                {
                    var index = marchEntityPool.Count - 1;
                    entity = marchEntityPool[index];
                    marchEntityPool.RemoveAt(index);
                }
            }
            else
            {
                
                if (monsterEntityPool.Count == 0)
                {
                    entity = CreateNewMarchEntity(true);
                }
                else
                {
                    var index = monsterEntityPool.Count - 1;
                    entity = monsterEntityPool[index];
                    monsterEntityPool.RemoveAt(index);
                }
            }
            
            entity.Mono.enabled = true;
            entity.RtsServerInfo = RTSClassPoolManager.GetRtsServerInfo();
            
            return entity;
        }

        private readonly Vector3 INVISIBLE_POSITION = new Vector3(-99999,-99999,-99999);
        
        private void RecoverMarchEntity(MarchEntity marchEntity)
        {
            if (marchEntity.AudioEmitter!=null)
            {
                marchEntity.AudioEmitter.enabled = false;
            }
            marchEntity.Mono.enabled = false;
            //marchEntity.Transform.SetParent(marchEntityRoot);
            marchEntity.Transform.position = INVISIBLE_POSITION;
            if (marchEntity.ClientMarchType == EClientMarchType.Monster)
            {
                monsterEntityPool.Add(marchEntity);   
#if UNITY_EDITOR
                marchEntity.GetGameObject().name = monsterEntityObjName;
#endif
            }
            else
            {
                marchEntityPool.Add(marchEntity);
#if UNITY_EDITOR
                marchEntity.GetGameObject().name = marchEntityObjName;
#endif
            }
        }

        public void ResetFormation()
        {
            for (int i = 0; i < marchEnitiesBase.Count; i++)
            {
                marchEnitiesBase[i].ResetFormation();
            }
        }

        private void PauseEventHandler(bool obj)
        {
            if (obj)
            {
                _lastClientTime = TimeUtils.GetClientTickTime();  //这里需要重置一下这个时间，要不然暂停失去焦点会导致有问题
                SquareDataManager.Instance.ForceSetMarchStatusAll();
            }
        }

        public List<MarchEntity> Marches => marchEnitiesBase;

        public ref Segment GetSegment(int index)
        {
            return ref segments[index];
        }
        [LuaCallCSharp]
        public void UpdateAllianceId(string allianceCode)
        {
            this.allianceCode = allianceCode;
        }
        [LuaCallCSharp]
        public void UpdateTroopTargetPosition(float x,float z, long troopId, int type)
        {
            if (!rtsEntityDictionary.TryGetValue((TargetCoordinateType)type, out var dictionary))
            {
                return;
            }
            if (!dictionary.TryGetValue(troopId,out var itemIndex))
            {
                return;
            }

            Vector3 targetPosition = new Vector3(x,0,z);
            var marchEntity = marchEnitiesBase[itemIndex];
            marchEntity.RtsServerInfo.targetPosition = targetPosition;
            marchEntity.SetForward((targetPosition - marchEntity.Position).normalized);
        }
      

        #region 创建、删除March

        [LuaCallCSharp]
        public MarchEntity CreateMarch(long troopId,int team,EClientMarchType eClientMarchType,int targetCoordinateType)
        {
            k_CreateMarchProfilerMarker.Begin();
            // 替代RTSManager.CreateMarch来创建MarchEntity
            // 分配 MarchIndex, 并创建 TroopPath
            
            if (troopId == 0)
            {
                throw new ArgumentNullException(nameof(troopId));
            }

            Transform rootTranfrom = null;
            if (eClientMarchType == EClientMarchType.March)
            {
                rootTranfrom = marchRootTransform;
                CurrentMarchNum++;
            }
            else if (eClientMarchType == EClientMarchType.Monster)
            {
                rootTranfrom = monsterRootTransform;
            }
            else
            {
                rootTranfrom = simpleRootTransform;
            }

            MarchEntity marchEntity = GetMarchEntityFromPool(eClientMarchType == EClientMarchType.Monster);
            
            var targetCoordinateTypeEnum = (TargetCoordinateType) targetCoordinateType;

            marchEntity.Initialize(troopId,team,eClientMarchType,targetCoordinateTypeEnum);
            
           
            var go = marchEntity.GetGameObject();
            //go.transform.parent = rootTranfrom;

            MarchMono res = go.GetComponent<MarchMono>();
            res.Init(marchEntity.ClientMarchType,marchEntity.Tid,targetCoordinateTypeEnum);
            //marchEntity.Mono = res;

            if (marchEntity.AudioEmitter == null)
            {
                marchEntity.AudioEmitter = res.marchAudioEmitter?.AddComponent<AudioEmitter3D>();
                marchEntity.AudioEmitter.UpdateFrequency = UpdateFrequency.Low; //low是每9fps更新一次位置，应该够用了
            }
            else
            {
                marchEntity.AudioEmitter.enabled = true;
            }
            
            // marchEntity.MarchInfo.SetTeam(team);
            marchEnitiesBase.Add(marchEntity);
            if (!rtsEntityDictionary.TryGetValue(targetCoordinateTypeEnum,out var dictionary))
            {
                dictionary = new Dictionary<long, int>();
                rtsEntityDictionary.Add(targetCoordinateTypeEnum,dictionary);
            }

            if (!dictionary.ContainsKey(troopId))
            {
                dictionary.Add(troopId,count);
            }
            
            marchEntity.MarchManager = this;
            marchEntity.MarchInfo.MarchIndex = count;

            var troopPath = ClassManager.Get<TroopPath>();
            paths.Add(troopPath);

            count++;
            
            k_CreateMarchProfilerMarker.End();

            return marchEntity;
        }
        [LuaCallCSharp]
        public MarchEntity CreateMonsterMarch(long troopId, int team, int monsterType)
        {
            var march = CreateMarch(troopId,team, EClientMarchType.Monster,(int)TargetCoordinateType.MONSTER_4);

            march.SetMonsterRadius(monsterType);
            return march;
        }
        private void CheckSimpleModeOpen()
        {
           
            if (ArmyManager.NeverCheckSimpleMode)
            {
                return;
            }
            
            var avgFps = AverageFPS;
            Debug.LogFormat("CheckSimpleModeOpen : avgFps = {0}",avgFps);
            if (RTSQualityHelper.Quality == 0)
            {
                if (avgFps <= 18 || _currentMarchNum > 20)
                {
                    RTSQualityHelper.ChangeSimpleMode(true,true);
                }

                if (avgFps > 20)
                {
                    RTSQualityHelper.ChangeSimpleMode(false, true);
                }
            }
            else if(RTSQualityHelper.Quality == 1)
            {
                if (avgFps < 20 || _currentMarchNum > 40)
                {
                    RTSQualityHelper.ChangeSimpleMode(true,true);
                    
                }else if(avgFps > 22)
                {
                    RTSQualityHelper.ChangeSimpleMode(false, true);
                }
            }
            else
            {
                if (avgFps < 20 || _currentMarchNum > 60)
                {
                    RTSQualityHelper.ChangeSimpleMode(true, true);
                }

                if (avgFps > 24 && _currentMarchNum < 60)
                {
                    RTSQualityHelper.ChangeSimpleMode(false, true);
                }
            }
        }

        private Transform marchRootTransform;
        private Transform monsterRootTransform;
        private Transform simpleRootTransform;
        public void SetMarchAndMonsterRoot(Transform marchRoot, Transform monsterRoot,Transform SimpleRootTransform)
        {
            this.marchRootTransform = marchRoot;
            this.monsterRootTransform = monsterRoot;
            this.simpleRootTransform = SimpleRootTransform;
            //InitMarchEntityPool();
            if (marchEntityRoot)
            {
                marchEntityRoot.transform.SetParent(marchRoot);
            }
            if (monsterEntityRoot)
            {
                monsterEntityRoot.transform.SetParent(marchRoot);
            }
            if (SelectedObjRoot)
            {
                SelectedObjRoot.transform.SetParent(marchRoot);
            }
            
            MarchBesiegeManager.Instance.Initialize();
        }

        public Transform GetRoot()
        {
            return marchRootTransform;
        }
    

        /// <summary>
        /// 获取所有行军数据
        /// </summary>
        /// <returns></returns>
        public List<MarchEntity> GetAllMarchEntities()
        {
            return marchEnitiesBase;
        }

        public MarchEntity GetMarchEntityByIdAndType(long troopId, com.youzu.warh.protocol.TargetCoordinateType type)
        {
            if (rtsEntityDictionary.TryGetValue((TargetCoordinateType)type,out var dictionary))
            {
                if (dictionary.TryGetValue(troopId,out var index))
                {
                    if (index < marchEnitiesBase.Count)
                    {
                        return marchEnitiesBase[index];
                    }
                }
            }

            return null;
        }
        public MarchEntity GetMarchEntityByIdAndType(long troopId,TargetCoordinateType type)
        {
            if (rtsEntityDictionary.TryGetValue(type,out var dictionary))
            {
                if (dictionary.TryGetValue(troopId,out var index))
                {
                    if (index < marchEnitiesBase.Count)
                    {
                        return marchEnitiesBase[index];
                    }
                }
            }

            return null;
        }

        //用于lua端删除失败后客户端容错的删除列表
        private List<MarchEntity> delayDestroyMarchList = new List<MarchEntity>();
        private bool hasDelayDestroyMarch = false;
        
        public void DelayDestroyMarch(long troopKey,int type)
        {
            if (!rtsEntityDictionary.TryGetValue((TargetCoordinateType)type, out var dictionary))
            {
                return;
            }
            if (!dictionary.TryGetValue(troopKey,out var itemIndex))
            {
                return;
            }
            var marchEntity = marchEnitiesBase[itemIndex];
            if (marchEntity != null)
            {
                delayDestroyMarchList.Add(marchEntity);
                hasDelayDestroyMarch = true;
            }
        }
        
        /// <summary>
        /// 销毁行军数据
        /// </summary>
        /// <param name="troopKey"></param>
        [LuaCallCSharp]
        public void DestroyMarch(long troopKey,int type,bool immediately = false)
        {
            //Debug.LogError("删除行军 "+troopKey);
            k_DestroyMarch.Begin();
            if (troopKey == 0)
            {
                throw new ArgumentNullException(nameof(troopKey));
            }
            
            // 获取部队索引
            if (!rtsEntityDictionary.TryGetValue((TargetCoordinateType)type, out var dictionary))
            {
                return;
            }

            if (!dictionary.TryGetValue(troopKey,out var itemIndex))
            {
                return;
            }
            
            if (count <= 0)
            {
                Debug.LogErrorFormat("count == 0");
                return;
            }
            var troop = new Troop(troopKey,(TargetCoordinateType)type);

            if (targetIdAndSourceIdMap.TryGetValue(troop,out var list))
            {
                list.Clear();
                _listPool.RecoverItem(list);
                targetIdAndSourceIdMap.Remove(troop);
            }
            var marchEntity = marchEnitiesBase[itemIndex];
            int team = -1,targetTeam = -1;
            if(marchEntity!= null)
            {
                team = marchEntity.RtsServerInfo.team;
                targetTeam = marchEntity.RtsServerInfo.targetTeam;
            }

            // 删除行军线
            if (marchEntity.LineId > 0)
            {
                RTSLuaCallCSharpManager.DelMarchLine(marchEntity.LineId);
                marchEntity.LineId = 0;
            }

            //Profiler.BeginSample("DestroyMarhch.OnMarchRemoved");
            playerBattle.OnMarchRemoved(marchEntity);
            //Profiler.EndSample();
            //删除之前加入等待删除队列
            //Profiler.BeginSample("DestroyMarhch.AddToDeletList");
           
            if (marchEntity.ClientMarchType == EClientMarchType.March)
            {
                CurrentMarchNum--;
            }
            //Profiler.BeginSample("DestroyMarhch.OnBeforeDispose");
            marchEntity.OnBeforeDispose();
            //Profiler.EndSample();
            //Profiler.BeginSample("DestroyMarhch.StopPlayAudio");
            StopPlayAudio(troopKey,team,targetTeam,marchEntity);
            //Profiler.EndSample();
            RemovePlayer2March(troopKey,(TargetCoordinateType)type);

            // 都使用与最后一个元素交换的方法删除
            //Profiler.BeginSample("DestroyMarhch.FreePath");
            bool isLastItem = itemIndex == count - 1;

            var lastTroop = marchEnitiesBase[count - 1];
            lastTroop.MarchInfo.MarchIndex = itemIndex;

            ClassManager.Free(paths[itemIndex]);
            if (!isLastItem)
                paths[itemIndex] = paths[count - 1];
            
            paths.RemoveAt(count - 1);
            //Profiler.EndSample();
          
            //Profiler.BeginSample("DestroyMarhch.FreeSegment");
            if (!isLastItem)
            {
                segments[itemIndex] = segments[count - 1];
                segments[count - 1]._uid = 0;
            }
            else
            {
                segments[itemIndex]._uid = 0;
            }
            //Profiler.EndSample();
            //Profiler.BeginSample("DestroyMarhch.RemoveMarchEntity");
            if (!isLastItem)
                marchEnitiesBase[itemIndex] = lastTroop;
            marchEnitiesBase.RemoveAt(count - 1);

            long keyOfLastTroop = lastTroop.MarchInfo.Uid;

            if (rtsEntityDictionary.TryGetValue(lastTroop.TargetCoordinateType, out var removeDictionary))
            {
                if (removeDictionary.ContainsKey(keyOfLastTroop))
                {
                    removeDictionary[keyOfLastTroop] = itemIndex;
                }
            }

            dictionary.Remove(troopKey);
            count--;
            //Profiler.EndSample();
            k_DestroyMarch.End();

            if (ArmyManager.Instance.IsInSandBox && !immediately)
            {
                _waitDeleteEntityList.Add(marchEntity);
                //Profiler.EndSample();
                waitDeleteCount++;
            }
            else
            {
                var id = marchEntity.Tid;
                MarchBesiegeManager.Instance.RemoveAttackTarget(id,marchEntity.RtsServerInfo.Type);
                MarchBesiegeManager.Instance.RemoveReachTime(id,marchEntity.RtsServerInfo.Type);
                marchEntity.Dispose();
                RecoverMarchEntity(marchEntity);
            }
           
        }
        #endregion

        
        private com.youzu.warh.protocol.SCRoundFight cachedRoundFight;
        private float cachedRoundFightTime;

        public void DoArenaRoundFight(com.youzu.warh.protocol.SCRoundFight roundFight)
        {
            if (roundFight != null)
            {
                _roundFightPlayer.RoundFight(roundFight);
            }
        }
        
        public static void OnRoundFightInCity(com.youzu.warh.protocol.SCRoundFight roundFight)
        {
            if (roundFight != null && roundFight.fightInfo != null)
            {
                UpdateSoldierStruct soldierCountStruct = new UpdateSoldierStruct();
                for (int i = 0; i < roundFight.fightInfo.Count; i++)
                {
                    com.youzu.warh.protocol.TroopFightInfo info = roundFight.fightInfo[i];
                    // 分两种情况 判断
                    // 在内城 MarchManager.Instance 未初始化 为nil 直接更新 必定是自己部队的推送
                    // 在沙盘 判断 Team
                    bool inCity = MarchManager.Instance == null;
                    bool isSelf = false;
                    if (!inCity)
                    {
                        var marchEntity = MarchManager.Instance.GetMarchEntityByIdAndType(info.troop.uid,info.troop.type);
                        isSelf = marchEntity != null && marchEntity.Team == MarchHelper.TeamSelf;
                    }
                    if (inCity || isSelf)
                    {
                        soldierCountStruct.Tid = info.troop.uid;
                        soldierCountStruct.Type = (int)TargetCoordinateType.MARCH_3;
                        soldierCountStruct.InitSoldierCount = info.intSoldierNum;
                        soldierCountStruct.SoldierCount = info.curSoldierNum;
                        if (UpdateSoldierCallBack == null)
                        {
                            UpdateSoldierCallBack = LuaManager.mainState.Global.GetInPath<UpdateSoldierCallBack>("G_MarchManager.OnUpdateSoldierCallBack");
                        }
                        UpdateSoldierCallBack?.Invoke(soldierCountStruct);
                    }
                }
            }
        }
        
        private void OnRoundFight(com.youzu.warh.protocol.SCRoundFight roundFight)
        {
            //远征现在不走roundfight
            if (roundFight.scene == RtsScenes.EXPEDITION)
            {
                return;
            }
            //同时判断一下
            if ((roundFight.happenWorldId != sandBoxServerId))
            {
                Debug.LogFormat("OnRoundFight happenWorldId:{0} sandBoxServerId:{1} userServerId:{2}",roundFight.happenWorldId,sandBoxServerId,userServerId);
                return;
            }
            
            // 不管怎么样 更新自己部队的血量！！！！！！！
            OnRoundFightInCity(roundFight);

            //需要判断是否在沙盘 缓存数据
            if (!ArmyManager.Instance.IsInSandBox)
            {
                cachedRoundFightTime = TimeUtils.GetClientTickTime();
                cachedRoundFight = roundFight;
                return;
            }

            if (roundFight != null)
            {
                _roundFightPlayer.RoundFight(roundFight);
            }

        }

        public void OnLeaveSandBox()
        {
            //停一下音乐
            StopAllMusic();
            DeleteAllDeadEffect();
        }

        public void StopAllMusic()
        {
            foreach (var marchEntity in marchEnitiesBase)
            {
                var marchInfo = marchEntity.MarchInfo;
                var clientMarchStatus = marchEntity.MarchInfo.ClientMarchStatue;
                var serverData = marchEntity.RtsServerInfo;
                var isSelf = serverData.team == 0;
                if (marchInfo.IsInBattleState && clientMarchStatus == EMarchStatus.Battle && !isSelf)
                {
                    StopPlayAudio(marchEntity.Tid,marchEntity.Team,marchEntity.Team,marchEntity);
                }
            }
        }

        public void OnEnterSandBox()
        {
            //3秒过期
            if (cachedRoundFight != null && TimeUtils.GetClientTickTime() - cachedRoundFightTime <= 3)
            {
                _roundFightPlayer.RoundFight(cachedRoundFight);
            }
            cachedRoundFight = null;
            //检查一下播放音乐
            foreach (var marchEntity in marchEnitiesBase)
            {
                var marchInfo = marchEntity.MarchInfo;
                var clientMarchStatus = marchEntity.MarchInfo.ClientMarchStatue;
                var serverData = marchEntity.RtsServerInfo;
                var isSelf = serverData.team == 0;
                if (marchInfo.IsInBattleState && clientMarchStatus == EMarchStatus.Battle && !isSelf)
                {
                    PlayerBattleSound(clientMarchStatus, marchInfo.ClientMarchStatue, serverData.targetType, oldTargetType, marchEntity.GetAudioEmiterObject(), marchEntity.Tid, serverData.team,serverData.targetTeam,marchEntity);
                }
                else
                {
                    marchEntity.ChangeSquareStateByMarchType();
                }
            }
        }

        public void UpdateArenaKeyFrame(TroopMarchKeyFrame keyFrame, long startTime)
        {
            var troopId = keyFrame.troopId;
            if (troopId == 0)
            {
                //Debug.LogErrorFormat("TroopMarch.lod2.tid IsNullOrEmpty");
                return;
            }
            // 获取部队索引
            if (!rtsEntityDictionary.TryGetValue(TargetCoordinateType.MARCH_3, out var dictionary))
            {
                return;
            }

            if (!dictionary.TryGetValue(troopId,out var itemIndex))
            {
                return;
            }
            
            var marchEntity = marchEnitiesBase[itemIndex];
            var rtsServerInfo =
                RtsConvertDataFactory.ConvertData(marchEntity,keyFrame, marchEntity.Team, marchEntity.RtsServerInfo, startTime);
            UpdateTroop(itemIndex, rtsServerInfo);
        }
        
        [LuaCallCSharp]
        public void UpdateArenaBattleTroop(RtsArenaTroop troopData,int team,LuaArrAccess access,bool isFromDeck = false)
        {
            var troop = troopData.troop;
            var troopId = troop.troopId;
            if (troopId == 0)
            {
                //Debug.LogErrorFormat("TroopMarch.lod2.tid IsNullOrEmpty");
                return;
            }
            // 获取部队索引
            if (!rtsEntityDictionary.TryGetValue(TargetCoordinateType.MARCH_3, out var dictionary))
            {
                return;
            }

            if (!dictionary.TryGetValue(troopId,out var itemIndex))
            {
                return;
            }
            
            var marchEntity = marchEnitiesBase[itemIndex];

            
            var rtsServerInfo = RtsConvertDataFactory.ConvertData(troopData, team,marchEntity.RtsServerInfo,access);
            if (marchEntity.RtsServerInfo == null)
            {
                marchEntity.RtsServerInfo = rtsServerInfo;
            }
//#if UNITY_EDITOR
            marchEntity.GetGameObject().name = string.Format("Arena_{0}_{1}", team, troop.troopId);
//#endif
            marchEntity.isArenaMarch = true;
            marchEntity.isArenaMarchInDeck = isFromDeck;
            marchEntity.isPortraitRotated = ScreenOrientManager.GetInstance().IsPortrait();
            UpdateTroop(itemIndex, rtsServerInfo);
            marchEntity.MarchInfo.besiegeRadius = troopData.besiegeRadius;
            marchEntity.Transform.position = marchEntity.MarchInfo.Position;
            marchEntity.ForceSetPosition();
        }

        
         /// <summary>
        /// 攻击货车的假部队
        /// </summary>
        /// <param name="troopMarch"></param>
        [LuaCallCSharp]
        public void CreateTruckAttackerMarch(TroopMarch troopMarch,TroopMarch defenderTroopMarch,bool isAttackerWin)
        {
            if (Debug.isDebugBuild)
            {
                UnityEngine.Debug.Log("Truck货车开始攻击" + troopMarch.lod3.soldierType + " " +
                                      defenderTroopMarch.lod3.soldierType);
            }
            var troopId = troopMarch.lod3.tid;
            CurrentMarchNum++;

            MarchEntity marchEntity = GetMarchEntityFromPool();
            
            var targetCoordinateTypeEnum = TargetCoordinateType.MARCH_3;

            marchEntity.Initialize(troopId,MarchHelper.TeamSelf,EClientMarchType.March,targetCoordinateTypeEnum);

            var go = marchEntity.GetGameObject();
            //go.transform.parent = rootTranfrom;

            MarchMono res = go.GetComponent<MarchMono>();
            res.Init(marchEntity.ClientMarchType,marchEntity.Tid,targetCoordinateTypeEnum);
            //marchEntity.Mono = res;

            if (marchEntity.AudioEmitter == null)
            {
                marchEntity.AudioEmitter = res.marchAudioEmitter?.AddComponent<AudioEmitter3D>();
                marchEntity.AudioEmitter.UpdateFrequency = UpdateFrequency.Low; //low是每9fps更新一次位置，应该够用了
            }
            else
            {
                marchEntity.AudioEmitter.enabled = true;
            }
            
            marchEnitiesBase.Add(marchEntity);
            if (!rtsEntityDictionary.TryGetValue(targetCoordinateTypeEnum,out var dictionary))
            {
                dictionary = new Dictionary<long, int>();
                rtsEntityDictionary.Add(targetCoordinateTypeEnum,dictionary);
            }

            if (!dictionary.ContainsKey(troopId))
            {
                dictionary.Add(troopId,count);
            }
            
            marchEntity.MarchManager = this;
            marchEntity.MarchInfo.MarchIndex = count;

            var troopPath = ClassManager.Get<TroopPath>();
            paths.Add(troopPath);

           
            var rtsServerInfo = RtsConvertDataFactory.ConvertData(troopMarch, marchEntity.RtsServerInfo,null);
            rtsServerInfo.soldierCount = 100;
            rtsServerInfo.initSoldierCount = 100;
            var targetId = rtsServerInfo.targetId;
            var targetMarchEntity = GetMarchEntityByIdAndType(targetId,TargetCoordinateType.INTERCITY_TRADE_TRUCK_45);
            
            float crushTime = 0;
            float crushDuration = 0;
            float totalCrushTime = 0;
            Vector3 crushDirection = default;
            if (rtsEntityDictionary.TryGetValue(TargetCoordinateType.INTERCITY_TRADE_TRUCK_45, out var dic))
            {
                if (dic.TryGetValue(targetId, out var index))
                {
                    var targetTroopPath = paths[index];
                    var path = targetTroopPath.Points;
                    var newPath = new List<Coordinate>();
                    var targetSpeed = targetMarchEntity.RtsServerInfo.speed * 10;
                    targetSpeed = Mathf.Min(targetSpeed, 1000);
                    for (int i = 0; i < path.Count; i++)
                    {
                        Vector3 pathForward;
                        //获取线段的方向
                        if (i == 0)
                        {
                            if (path.Count > 1)
                            {
                                pathForward = path[1] - path[0];
                            }
                            else
                            {
                                pathForward = targetMarchEntity.Forward;
                            }
                        }
                        else
                        {
                            pathForward = path[i] - path[i - 1];
                        }

                        pathForward = pathForward.normalized;
                        var offset = Quaternion.AngleAxis(90, Vector3.up) * pathForward * 0.5f;
                        
                        if (i == 0)
                        {
                            newPath.Add((targetMarchEntity.Position + offset - pathForward * targetSpeed / 3600 * 1.5f).ToCoordinate());
                            //平行时间
                            var time1 = 2f;
                            //开始靠近时间
                            var time2 = 1f;
                            //撞击时间
                            var time3 = 0.1f;
                            //开始远离时间
                            var time4 = 0.5f;
                            
                            //每秒速度
                            var speed = targetMarchEntity.RtsServerInfo.speed / 3600;

                            crushDuration = time3;
                            var reverseCrushDirection = Quaternion.AngleAxis(90, Vector3.up) * pathForward.normalized;
                            crushDirection = -reverseCrushDirection;
                            
                            //选择一个撞击点
                            var start = path[0] + pathForward * speed * time1 + reverseCrushDirection * 0.4f;
                            //var hitPoint1 = path[0] + pathForward * speed * (time1 + time2) + reverseCrushDirection * 0.2f;
                            //var hitPoint2 = path[0] + pathForward  * speed * (time1 + time2 + time3) + reverseCrushDirection * 0.2f;
                            var end = path[0] + pathForward * speed * (time1 + time2 + time3 + time4) + reverseCrushDirection * 0.4f;
                            
                            //newPath.Add(start.ToCoordinate());
                            //newPath.Add(hitPoint1.ToCoordinate());
                            //newPath.Add(hitPoint2.ToCoordinate());
                            //newPath.Add(end.ToCoordinate());
                            crushTime = Time.time + (time1 + time2);
                            totalCrushTime = 3; //time1 + time2 + time3 + time4;
                        }
                        else
                        {
                            newPath.Add((path[i] + offset).ToCoordinate());
                        }
                    }
                    rtsServerInfo.coordinate = newPath[0];
                    rtsServerInfo.pathList = newPath.ToArray();
                    rtsServerInfo.speed = targetSpeed;
                }
            }
            
            if (marchEntity.RtsServerInfo == null)
            {
                marchEntity.RtsServerInfo = rtsServerInfo;
            }

            if (targetMarchEntity != null)
            {
                targetMarchEntity.RtsServerInfo.heroQualityList = defenderTroopMarch.lod3.heroQualityList;
                targetMarchEntity.RtsServerInfo.heroIconList = defenderTroopMarch.lod3.heroIconList;
                targetMarchEntity.RtsServerInfo.heroRageList = defenderTroopMarch.lod3.heroRageList;
                targetMarchEntity.RtsServerInfo.SoldierType = defenderTroopMarch.lod3.soldierType;
#if UNITY_EDITOR
                marchEntity.GetGameObject().name = string.Format("TruckAttacker_{0}", troopId);
#endif
                marchEntity.ClientCreateMarch = 1;
                rtsServerInfo.visible = true;
                UpdateTroop(count, rtsServerInfo,true);
                marchEntity.SetHeroIcon(rtsServerInfo);
                marchEntity.SetPlayerTitle();
                marchEntity.SetNickName("TruckAttacker");
                marchEntity.Transform.position = marchEntity.MarchInfo.Position;
                marchEntity.ForceSetPosition();
                marchEntity.FadeIn(1);
                marchEntity.MarchInfo.SetIsClientInBattle(true);
                marchEntity.SetBattleTargetId(targetMarchEntity.Tid,targetMarchEntity.TargetCoordinateType);
                marchEntity.SetIsTruckFighting(true);
                marchEntity.StartPlayTruckAttacking(targetMarchEntity,isAttackerWin,isAttackerWin);
                ((MarchHud)targetMarchEntity.Hud)?.SetEntityAndTroopData(targetMarchEntity,
                    targetMarchEntity.RtsServerInfo);
                targetMarchEntity.MarchInfo.SetIsClientInBattle(true);
                targetMarchEntity.SetBattleTargetId(marchEntity.Tid,marchEntity.TargetCoordinateType);
                targetMarchEntity.SetIsTruckFighting(true);

            }
            else
            {
                marchEntity.ReadyToHide();
            }
            
            
            count++;

        }

        #region 列车新增

        /// <summary>
        /// 攻击列车的假部队 -单个
        /// <param name="battleIdx">战斗的idx 列车有三场战斗</param>
        /// </summary>
        [LuaCallCSharp]
        public void CreateTrainAttackerMarch(TroopMarch troopMarch,TroopMarch defenderTroopMarch,bool isAttackerWin,int battleIdx,bool isWin,string battleRes)
        {
            // 创建
            var troopId = troopMarch.lod3.tid;
            var targetId = troopMarch.lod3.targetId;
            var targetMarchEntity = GetMarchEntityByIdAndType(targetId,TargetCoordinateType.TRAIN_51);
            // 如果不是中间的部队 需要创建两个客户端虚拟的MarchEntity
            if (battleIdx != 1)
            {
                targetMarchEntity = CreateTrainDefenceMarch(troopMarch, defenderTroopMarch, battleIdx);
                targetId = targetMarchEntity.RtsServerInfo.targetId;
                troopMarch.lod3.targetId = targetMarchEntity.RtsServerInfo.targetId;
            }
            CurrentMarchNum++;
            MarchEntity marchEntity = GetMarchEntityFromPool();
            var targetCoordinateTypeEnum = TargetCoordinateType.MARCH_3;
            marchEntity.Initialize(troopId,MarchHelper.TeamSelf,EClientMarchType.March,targetCoordinateTypeEnum);
            var go = marchEntity.GetGameObject();
            MarchMono res = go.GetComponent<MarchMono>();
            res.Init(marchEntity.ClientMarchType,marchEntity.Tid,targetCoordinateTypeEnum);

            if (marchEntity.AudioEmitter == null)
            {
                marchEntity.AudioEmitter = res.marchAudioEmitter?.AddComponent<AudioEmitter3D>();
                marchEntity.AudioEmitter.UpdateFrequency = UpdateFrequency.Low; //low是每9fps更新一次位置，应该够用了
            }
            else
            {
                marchEntity.AudioEmitter.enabled = true;
            }
            
            marchEnitiesBase.Add(marchEntity);
            if (!rtsEntityDictionary.TryGetValue(targetCoordinateTypeEnum,out var dictionary))
            {
                dictionary = new Dictionary<long, int>();
                rtsEntityDictionary.Add(targetCoordinateTypeEnum,dictionary);
            }

            if (!dictionary.ContainsKey(troopId))
            {
                dictionary.Add(troopId,count);
            }
            marchEntity.MarchManager = this;
            marchEntity.MarchInfo.MarchIndex = count;
            count++;
            // 数据
            var troopPath = ClassManager.Get<TroopPath>();
            paths.Add(troopPath);
            var rtsServerInfo = RtsConvertDataFactory.ConvertData(troopMarch, marchEntity.RtsServerInfo,null);
            rtsServerInfo.soldierCount = 100;
            rtsServerInfo.initSoldierCount = 100;
     
            // 路点
            if (rtsEntityDictionary.TryGetValue(TargetCoordinateType.TRAIN_51, out var dic))
            {
                if (dic.TryGetValue(targetId, out var index))
                {
                    var targetTroopPath = paths[index];
                    var path = targetTroopPath.Points;
                    var newPath = new List<Coordinate>();
                    var targetSpeed = targetMarchEntity.RtsServerInfo.speed * 10;
                    targetSpeed = Mathf.Min(targetSpeed, 1000);
 
                    for (int i = 0; i < path.Count; i++)
                    {
                        Vector3 pathForward;
                        //获取线段的方向
                        if (i == 0)
                        {
                            if (path.Count > 1)
                            {
                                pathForward = path[1] - path[0];
                            }
                            else
                            {
                                pathForward = targetMarchEntity.Forward;
                            }
                        }
                        else
                        {
                            pathForward = path[i] - path[i - 1];
                        }

                        pathForward = pathForward.normalized;
                        float offset_L = battleIdx == 1 ? 1f : 0.7f;
                        var offset = Quaternion.AngleAxis(90, Vector3.up) * pathForward * offset_L;// 这个是平行的距离
                        
                
                        if (i == 0)
                        {
                            newPath.Add((targetMarchEntity.Position + offset - pathForward * targetSpeed / 3600 * 1.5f).ToCoordinate());
                        }
                        else
                        {
                            newPath.Add((path[i] + offset).ToCoordinate());
                        }
                    }
                    rtsServerInfo.coordinate = newPath[0];
                    rtsServerInfo.pathList = newPath.ToArray();
                    rtsServerInfo.speed = targetSpeed;
                }
            }
            // 初始化
            if (marchEntity.RtsServerInfo == null)
            {
                marchEntity.RtsServerInfo = rtsServerInfo;
            }
          
            if (targetMarchEntity != null)
            {
                targetMarchEntity.RtsServerInfo.heroQualityList = defenderTroopMarch.lod3.heroQualityList;
                targetMarchEntity.RtsServerInfo.heroIconList = defenderTroopMarch.lod3.heroIconList;
                targetMarchEntity.RtsServerInfo.heroRageList = defenderTroopMarch.lod3.heroRageList;
                targetMarchEntity.RtsServerInfo.SoldierType = defenderTroopMarch.lod3.soldierType;
                targetMarchEntity.RtsServerInfo.isNullTroop = defenderTroopMarch.isNullTroop;
#if UNITY_EDITOR
                marchEntity.GetGameObject().name = string.Format("TrainAttacker_{0}", troopId);
#endif
                marchEntity.ClientCreateMarch = 2;
                rtsServerInfo.visible = true;
                UpdateTroop(marchEntity.MarchInfo.MarchIndex, rtsServerInfo,true);
                marchEntity.SetHeroIcon(rtsServerInfo);
                marchEntity.SetPlayerTitle();
                marchEntity.SetNickName("TrainAttacker");
                marchEntity.Transform.position = marchEntity.MarchInfo.Position;
                marchEntity.ForceSetPosition();
                marchEntity.FadeIn(1);
                //marchEntity.MarchInfo.SetIsClientInBattle(true);
                marchEntity.SetBattleTargetId(targetMarchEntity.Tid,targetMarchEntity.TargetCoordinateType);
                marchEntity.SetIsTrainFighting(true);
                marchEntity.StartPlayTruckAttacking(targetMarchEntity,isAttackerWin,isWin,battleIdx, battleRes, battleIdx * 1f);
                ((MarchHud)targetMarchEntity.Hud)?.SetEntityAndTroopData(targetMarchEntity,
                    targetMarchEntity.RtsServerInfo);
                //targetMarchEntity.MarchInfo.SetIsClientInBattle(true);
                targetMarchEntity.SetBattleTargetId(marchEntity.Tid,marchEntity.TargetCoordinateType);
                targetMarchEntity.SetIsTrainFighting(!defenderTroopMarch.isNullTroop);
            }
            else
            {
                marchEntity.ReadyToHide();
            }
       
        }

        private int ClientTrainBattleMarchTid = 10000;// 客户端创建的虚假的列车防守部队id
        /// <summary>
        /// 防守列车的假部队 -单个
        /// </summary>
        [LuaCallCSharp]
        public MarchEntity CreateTrainDefenceMarch(TroopMarch troopMarch,TroopMarch defenderTroopMarch,int battleIdx)
        {
            MarchEntity trainMarchEntity = GetMarchEntityByIdAndType(troopMarch.lod3.targetId,TargetCoordinateType.TRAIN_51);
            // 创建
            int troopId = ClientTrainBattleMarchTid;
            CurrentMarchNum++;
            MarchEntity marchEntity = GetMarchEntityFromPool();
            marchEntity.ClientCreateMarch = 3; // 设置列车防守部队标记
            var targetCoordinateTypeEnum = TargetCoordinateType.TRAIN_51;
            marchEntity.Initialize(troopId,MarchHelper.TeamSelf,EClientMarchType.Train,targetCoordinateTypeEnum);
            var go = marchEntity.GetGameObject();
            MarchMono res = go.GetComponent<MarchMono>();
            res.Init(marchEntity.ClientMarchType,marchEntity.Tid,targetCoordinateTypeEnum,false); // 模拟的部队不需要点击 

            if (marchEntity.AudioEmitter == null)
            {
                marchEntity.AudioEmitter = res.marchAudioEmitter?.AddComponent<AudioEmitter3D>();
                marchEntity.AudioEmitter.UpdateFrequency = UpdateFrequency.Low; //low是每9fps更新一次位置，应该够用了
            }
            else
            {
                marchEntity.AudioEmitter.enabled = true;
            }
            
            marchEnitiesBase.Add(marchEntity);
            if (!rtsEntityDictionary.TryGetValue(targetCoordinateTypeEnum,out var dictionary))
            {
                dictionary = new Dictionary<long, int>();
                rtsEntityDictionary.Add(targetCoordinateTypeEnum,dictionary);
            }

            if (!dictionary.ContainsKey(troopId))
            {
                dictionary.Add(troopId,count);
            }
            marchEntity.MarchManager = this;
            marchEntity.MarchInfo.MarchIndex = count;

            var troopPath = ClassManager.Get<TroopPath>();
            paths.Add(troopPath);
            
            // 数据
            var rtsServerInfo = RtsConvertDataFactory.ConvertData(defenderTroopMarch, marchEntity.RtsServerInfo,null);
            rtsServerInfo.soldierCount = 100;
            rtsServerInfo.initSoldierCount = 100;
            // 路点
            rtsServerInfo.coordinate = new Coordinate();
            Vector3 pathForward;
            //获取线段的方向
            pathForward = trainMarchEntity.Forward;
            pathForward = pathForward.normalized;
            var offset = pathForward * (1 - battleIdx) * 0.5f; // 根据battleIdx 前后偏移 0.5f
            rtsServerInfo.coordinate = (trainMarchEntity.Position + offset).ToCoordinate();
            rtsServerInfo.pathList = trainMarchEntity.RtsServerInfo.pathList;
            rtsServerInfo.speed = trainMarchEntity.RtsServerInfo.speed;
            
            // 初始化
            marchEntity.RtsServerInfo = rtsServerInfo;
#if UNITY_EDITOR
            marchEntity.GetGameObject().name = string.Format("TrainClientDefence_{0}", troopId);
#endif
            rtsServerInfo.visible = true;
            UpdateTroop(count, rtsServerInfo,true);
            marchEntity.SetForward(trainMarchEntity.Forward);
            marchEntity.SetHeroIcon(rtsServerInfo);
            marchEntity.SetPlayerTitle();
            marchEntity.SetNickName("");
            marchEntity.Transform.position = marchEntity.MarchInfo.Position;
            marchEntity.ForceSetPosition();
            marchEntity.MarchInfo.SetIsClientInBattle(true);
            trainMarchEntity.isTrainFighting = true;
            marchEntity.StartPlayTrainDefending(marchEntity,trainMarchEntity,battleIdx);
            count++;
            ClientTrainBattleMarchTid++;
            return marchEntity;
        }

        #endregion

        #region 同步部队or 野怪信息

        /// <summary>
        /// 同步部队信息
        /// </summary>
        /// <param name="troopMarch"></param>
        [LuaCallCSharp]
        public void UpdateTroopMarchInfo(TroopMarch troopMarch, LuaArrAccess arrAccess,bool isForceRefresh = false)
        {
            var troopId = troopMarch.lod3.tid;
            if (troopId == 0)
            {
                //Debug.LogErrorFormat("TroopMarch.lod2.tid IsNullOrEmpty");
                return;
            }
            // 获取部队索引
            if (!rtsEntityDictionary.TryGetValue(troopMarch.lod3.troopType, out var dictionary))
            {
                return;
            }

            if (!dictionary.TryGetValue(troopId,out var itemIndex))
            {
                return;
            }

            if (ArmyManager.IsDebug)
            {
                Debug.LogError("TroopMarchInfo: "+ troopId +" 时间戳:"+TimeUtils.GetClientTickTimeMS());
            }
            var marchEntity = marchEnitiesBase[itemIndex];

            // 后端没有把货车的护送阵容发过来，heroIconList 永远是 { "icon_hero_army_empty" }
            // 真正的英雄头像在掠夺货车时才通过 CreateTruckAttackerMarch() 发送
            // 所以不要用这里的 troopMarch.heroIconList 覆盖掉已有的真数据
            if (marchEntity.RtsServerInfo != null && marchEntity.RtsServerInfo.Type == TargetCoordinateType.INTERCITY_TRADE_TRUCK_45)
            {
                troopMarch.lod3.heroIconList = null;
                troopMarch.lod3.heroQualityList = null;
            }

            var rtsServerInfo = RtsConvertDataFactory.ConvertData(troopMarch, marchEntity.RtsServerInfo,arrAccess);
            if (marchEntity.RtsServerInfo == null)
            {
                marchEntity.RtsServerInfo = rtsServerInfo;
            }

            if (troopMarch.expeditionDeck)
            {
                marchEntity.GetGameObject().name = string.Format("Arena_{0}_{1}", rtsServerInfo.team, troopId);
            }
            marchEntity.isExpeditionMarch = troopMarch.expeditionMarch;
            marchEntity.isExpeditionMarchInDeck = troopMarch.expeditionDeck;
            marchEntity.isExpeditionMarchMoving = troopMarch.expeditionMoving;
            marchEntity.bIsCargoTruckFakeMarch = troopMarch.bIsCargoTruckFakeMarch;

            marchEntity.isPortraitRotated =
                (troopMarch.expeditionMarch || troopMarch.expeditionDeck) && ScreenOrientManager.GetInstance().IsPortrait();
            
            UpdateTroop(itemIndex, rtsServerInfo, isForceRefresh);

            if (isForceRefresh)
            {
                marchEntity.Transform.position = marchEntity.MarchInfo.Position;
                marchEntity.ForceSetPosition();
            }
        }
        [BlackList]
        public void UpdateTroop(int itemIndex, RtsServerInfo rtsServerInfo,bool isForceRefresh = false)
        {
            var troopPath = paths[itemIndex];
            ref var segment = ref segments[itemIndex];
            var marchEntity = marchEnitiesBase[itemIndex];
            // 丢弃老的同步帧
            var lastFrameTime = rtsServerInfo.lastFrameTime;
            if (lastFrameTime > 0 && troopPath.LastServerTime > lastFrameTime)
            {
                //Debug.Log(LogModule.RTS, $"丢弃老的同步帧....troopId={troopId}");
                return;
            }
           
            var coordinate = rtsServerInfo.coordinate;
            marchEntity.MarchInfo.Coordinate = new Vector3(coordinate.xAxis, 0, coordinate.zAxis);

            ProcessBesiegeInfo(rtsServerInfo);
            // 获取部队信息
//            k_UpdateTroopMarchBaseInfo2.Begin();
            /*var simulatedBesiegeAngle = marchEntity.GetSimulatedBesiegeAngle();
            if (originBesiege >= 0 && simulatedBesiegeAngle >= 0 && originBesiege != marchEntity.GetSimulatedBesiegeAngle())
            {
                Debug.LogError(troopId+" 服务器夹击与模拟夹击不一致，模拟"+ marchEntity.GetSimulatedBesiegeAngle() + " 服务器" + originBesiege);
            }*/
            //debug，调试数据
            var lastPosition = marchEntity.Position;
            //Debug.LogError(troopId + marchEntity.Position.x + " " + troopMarch.lod4.coordinate.xAxis + "|" + marchEntity.Position.z + " " + troopMarch.lod4.coordinate.zAxis);

            if (!marchEntity.isFakeParent)
            {
                ProcessPlayerBattleRelation(rtsServerInfo);
            }

            var marchInfo = marchEntity.MarchInfo;
            var marchType = rtsServerInfo.marchType;
            //bool isUpdateName = marchInfo.UpdateFullName(troopMarch);
            //解散集结部队强制刷新下部队
//            if (marchInfo.serverData.lod2.isAssemblyLeader && !troopMarch.lod2.isAssemblyLeader)
//            {
//                marchEntity.ResetMarchSquare();
//            }
//            marchInfo.serverData = troopMarch;

            var soldierCount = ProcessSoldierHeroInfo(rtsServerInfo, marchEntity);

            ProcessCreateTroopHud(rtsServerInfo,marchEntity);
            
            JudgeSelfIsOtherTarget(marchEntity);

            bool isMarchTypeChanged = marchType != marchInfo.MarchType;
            ProcessSetMarchEntityInfoFromServerInfo(rtsServerInfo, marchEntity);

            ProcessTroopPath(rtsServerInfo, marchEntity,ref segment,troopPath, isForceRefresh);
            
//            k_UpdateTroopMarchBaseInfo3.Begin();
            ProcessTroopVisible(rtsServerInfo, marchEntity,lastPosition,soldierCount);
            ProcessClientStatus(rtsServerInfo,marchEntity,isMarchTypeChanged,soldierCount,troopPath);
            
            marchEntity.SetMarchDataToSquareData();
            marchEntity.MarchInfo.ClientAttackPosition = CalculateAttackPosition(rtsServerInfo, marchEntity);
            
            
            //判断被追击,通知攻击自己的人模拟路点
            if (marchEntity.MarchInfo.SoldierCount > 0 && (marchEntity.IsMoving() || (rtsServerInfo.pathList != null && rtsServerInfo.pathList.Length > 0)))
            {
                updateChaseAttackerList.Add(marchEntity);
            }
            if (rtsServerInfo.isFightConditionNotMet)
            {
                marchInfo.SetIsInBattle(false);
                marchInfo.SetIsClientInBattle(false);
                marchInfo.SetIsJustLeaveBattle(true);
                ((MarchHud)marchEntity.Hud)?.SetIsInBattle(false);
            }
        }

        public Vector3 CalculateAttackPosition(RtsServerInfo rtsServerInfo, MarchEntity marchEntity)
        {
            Vector3 attackPosition = Vector3.zero;
            //攻击行军 计算交战位置
            if (rtsServerInfo.marchType == MarchType.ATTACK_1 && rtsServerInfo.marchStatus == MarchStatus.WALK_1)
            {
                if (rtsServerInfo.team == 0 || rtsServerInfo.targetTeam == 0) //如果我攻击目标
                {
                    var target = marchEntity.GetTarget();
                    if (target != null && target.MarchInfo.SoldierCount > 0 && (target.RtsServerInfo.pathList == null || target.RtsServerInfo.pathList.Length == 0))
                    {
                        var direction = (marchEntity.Position - target.Position).normalized;
                        var maxAttackDistance = MarchHelper.attack_range_1 + target.RtsServerInfo.radius + marchEntity.RtsServerInfo.radius - MarchHelper.chaseAttackOffset;
                        var distance = Vector3.Distance(marchEntity.Position, target.Position);

                        if (distance > maxAttackDistance)
                        {
                            attackPosition = target.Position + direction * maxAttackDistance;
                        }
                        else
                        {
                            //attackPosition = target.Position + direction * distance;
                            marchEntity.ClientStartFight();
                        }
                    }
                }
            }
            return attackPosition;
        }

        private void ProcessFakeParent(long uid,long fakeParentId,MarchEntity marchEntity)
        {
            //是父亲
            if (fakeParentId == 0)
            {
                //注册父亲
                if (!marchEntity.isFakeParent)
                {
                    marchEntity.SetIsFakeParent();
                    fakeTroopParents[uid] = marchEntity;
                }
                marchEntity.UpdateSquareVisible(false);
            }
            //是孩子
            else if (fakeParentId > 0)
            {
                if (!marchEntity.isFakeChild)
                {
                    //把自己添加到父亲里
                    if (fakeTroopParentChildMatch.TryGetValue((int) marchEntity.TargetCoordinateType, out var match))
                    {
                        if (match.TryGetValue(uid, out var parentId))
                        {
                            if (fakeTroopParents.TryGetValue(parentId, out var parent))
                            {
                                marchEntity.isFakeChild = true;
                                parent.AddFakeChild(marchEntity);
                            }
                        }
                    }
                }

                if (fakeTroopCoordinate.TryGetValue((int) marchEntity.TargetCoordinateType,out var coord))
                {
                    if (coord.TryGetValue(uid, out var coordinate))
                    {
                        marchEntity.MarchInfo.Coordinate = new Vector3(coordinate.xAxis, 0, coordinate.zAxis);
                    }
                }
                
            }
        }

        [LuaCallCSharp]
        public void UpdateAssemblyMarchInfo(MapAssembly mapAssembly, LuaArrAccess arrAccess,bool isForceRefresh = false)
        {
            var assemblyId = mapAssembly.lod3.assemblyId;

            // 获取部队索引
            if (!rtsEntityDictionary.TryGetValue(TargetCoordinateType.ASSEMBLY_20, out var dictionary))
            {
                return;
            }

            if (!dictionary.TryGetValue(assemblyId,out var itemIndex))
            {
                return;
            }
            
            var marchEntity = marchEnitiesBase[itemIndex];
            
            var rtsServerInfo = RtsConvertDataFactory.ConvertData(mapAssembly, marchEntity.RtsServerInfo,arrAccess);
            if (marchEntity.RtsServerInfo == null)
            {
                marchEntity.RtsServerInfo = rtsServerInfo;
            }

            if (rtsServerInfo.buildingUid != 0)
            {
                marchEntity.RtsServerInfo.visible = false;
            }

            UpdateTroop(itemIndex, rtsServerInfo);
            if (isForceRefresh)
            {
                marchEntity.Transform.position = marchEntity.MarchInfo.Position;
                marchEntity.ForceSetPosition();
            }
        }
        List<Troop> deleteAttackTargetList = new List<Troop>(10);
        private EMarchStatus GetClientMarchType(RtsServerInfo serverInfo)
        {
            var clientMarchStatus = EMarchStatus.Park;
            var marchType = serverInfo.marchType;
            var marchStatus = serverInfo.marchStatus;
            var pathList = serverInfo.pathList;
            if (serverInfo.IsCrossingGate)
            {
                clientMarchStatus = EMarchStatus.CrossingGate;
                RoundFightPlayer.Inst.RemoveDirectionEffect(serverInfo.tid);
            }
            else if (marchType == MarchType.DIE_5)
            {
                clientMarchStatus = EMarchStatus.Escape;
                RoundFightPlayer.Inst.RemoveDirectionEffect(serverInfo.tid);
            }
            else if (marchType == MarchType.DEFENCE_6 && marchStatus == MarchStatus.SIEGE_FIGHT_6)
            {
                //当防守部队 状态处于SIEGE_FIGHT_6时 表示该部队被击溃 已进入城防战状态 所以头像应该隐藏
                // clientMarchStatus = EMarchStatue.Escape;
                clientMarchStatus = EMarchStatus.SIEGE_FIGHT;
            }
            else if (pathList != null && pathList.Length > 1)
            {
                if (marchStatus == MarchStatus.FIGHT_2)
                {
                    if (serverInfo.besiegeRadius > 0 && serverInfo.besiegeFinalAngle >= 0)
                    {
                        clientMarchStatus = EMarchStatus.Besiege;
                    }
                    else
                    {
                        clientMarchStatus = EMarchStatus.Chasing;
                    }

                }
                else
                {
                    // 行军 （停止之后，变成驻扎状态）
                    clientMarchStatus = EMarchStatus.WALK;
                }
            }
            else if (marchStatus == MarchStatus.GARRISON_3 && serverInfo.buildingUid == 0 && (pathList == null || pathList.Length == 0))
            {
                // 驻扎
                clientMarchStatus = EMarchStatus.Park;
            }
            else if ((marchStatus == MarchStatus.FIGHT_2 || marchStatus == MarchStatus.SIEGE_FIGHT_6) &&
                     (pathList == null || pathList.Length == 0))
            {
                // 战斗
                clientMarchStatus = EMarchStatus.Battle;
            }
            else if ((marchStatus == MarchStatus.COLLECT_5) && (pathList == null || pathList.Length == 0))
            {
                // 采集部队到达采集点，释放掉方阵
                clientMarchStatus = EMarchStatus.Collect;
            } else if (marchType == MarchType.AID_8 || serverInfo.buildingUid != 0)
            {
                clientMarchStatus = EMarchStatus.InBuilding;
            }
            else if (marchStatus == MarchStatus.RESCUE_7 )
            {
                //营救状态，需要表现上使用walk
                clientMarchStatus = EMarchStatus.WALK;
            }
            return clientMarchStatus;
        }

        private EMarchStatus GetClientMarchType(RtsMapMonster monster)
        {
            var clientMarchStatus = EMarchStatus.Park;
            var lod3 = monster.lod3;
            if (lod3.marchStatus == MarchStatus.WALK_1)
            {
                clientMarchStatus = EMarchStatus.WALK;
            }
            else if(lod3.marchStatus == MarchStatus.GARRISON_3)
            {
                clientMarchStatus = EMarchStatus.Park;
            }
            else if (lod3.marchStatus == MarchStatus.FIGHT_2)
            {
                clientMarchStatus = EMarchStatus.Battle;
            }

            return clientMarchStatus;
        }
        [LuaCallCSharp]
        public void UpdateAllianceInfo(TroopMarch troopMarch)
        {

            var troopId = troopMarch.lod3.tid;
            //  Debug.LogFormat("====================\n{0}",troopMarch.lod2.ToString());
            if (troopId == 0)
            {
                Debug.LogErrorFormat("TroopMarch.lod2.tid IsNullOrEmpty");
                return;
            }
            
            // 获取部队索引
            if (!rtsEntityDictionary.TryGetValue(TargetCoordinateType.MARCH_3, out var dictionary))
            {
                return;
            }

            if (!dictionary.TryGetValue(troopId,out var itemIndex))
            {
                return;
            }
//            // 获取部队索引
//            if (!itemKeyAndIndexMap.TryGetValue(troopId, out int itemIndex))
//            {
//                Debug.LogErrorFormat("tid: {0} not found", troopId);
//                return;
//            }

            // 获取部队信息
            var marchEntity = marchEnitiesBase[itemIndex];

            if (troopMarch.lod3.team != marchEntity.MarchInfo.Team)
            {


                if (marchEntity.LineId > 0)  //删除之前的
                {
                    RTSLuaCallCSharpManager.DelMarchLine(marchEntity.LineId);
                    marchEntity.LineId = 0;
                }

                var troopPath = paths[itemIndex];
                if (troopPath.Points != null && troopPath.Points.Count > 0) //如果需要绘制新的，则绘制
                {
                    marchEntity.LineId = RTSLuaCallCSharpManager.DrawMarchLine(troopPath.Points, troopPath.SegmentIndex, troopMarch.lod3.team,troopMarch.lod2.isAssemblyLeader);
                }

                marchEntity.SetTeam(troopMarch.lod3.team);
                //marchEntity.Hud?.InitLod0Name(troopMarch);
            }
        }
        [LuaCallCSharp]
        public void UpdateTroopTeamInfo(long troopId, int type, int team)
        {
            if (troopId == 0)
            {
                Debug.LogErrorFormat("TroopMarch.lod2.tid IsNullOrEmpty");
                return;
            }
            
            // 获取部队索引
            if (!rtsEntityDictionary.TryGetValue((TargetCoordinateType)type, out var dictionary))
            {
                return;
            }

            if (!dictionary.TryGetValue(troopId,out var itemIndex))
            {
                return;
            }

            // 获取部队信息
            var marchEntity = marchEnitiesBase[itemIndex];
            if (marchEntity != null)
            {
                if (marchEntity.RtsServerInfo != null)
                {
                    marchEntity.RtsServerInfo.team = team;
                }
                marchEntity.SetTeam(team);
            }
        }
        public bool InInAllianceBuilding(MarchType marchType,MarchStatus marchStatus)
        {
            return marchType == MarchType.AID_8 && (marchStatus == MarchStatus.GARRISON_3);
        }
        /// <summary>
        /// 同步野怪信息
        /// </summary>
        /// <param name="monster"></param>
        [LuaCallCSharp]
        public void UpdateMonsterInfo(RtsMapMonster monster, LuaArrAccess arrAccess,bool forceUpdatePos = false)   
        {

            k_UpdateMonsterBaseInfo.Begin();
            var npcUid = monster.lod3.npcUid;
            if (npcUid == 0)
            {
                Debug.LogErrorFormat("RtsMapMonster.lod2.npcUid IsNullOrEmpty");
                return;
            }
            // 获取部队索引
            if (!rtsEntityDictionary.TryGetValue(TargetCoordinateType.MONSTER_4, out var dictionary))
            {
                return;
            }
            
            if (!dictionary.TryGetValue(monster.lod3.npcUid,out var itemIndex))
            {
                return;
            }

            var marchEntity = marchEnitiesBase[itemIndex];
            
            var rtsServerInfo = RtsConvertDataFactory.ConvertData(monster, marchEntity.RtsServerInfo,arrAccess);
            if (marchEntity.RtsServerInfo == null)
            {
                marchEntity.RtsServerInfo = rtsServerInfo;
            }
            var marchInfo = marchEntity.MarchInfo;
            marchInfo.Coordinate = new Vector3(rtsServerInfo.coordinate.xAxis,0,rtsServerInfo.coordinate.zAxis);
            if (rtsServerInfo.soldierListAccess !=null && rtsServerInfo.soldierListAccess.IsValid())
            {
                marchInfo.soldierListAccess = rtsServerInfo.soldierListAccess;
                marchInfo.SoldierListLength = rtsServerInfo.SoldierListLength;
            }
            marchEntity.isMonster = true;
            marchInfo.Uid = npcUid;
            
            var troopPath = paths[itemIndex];
            ref var segment = ref segments[itemIndex];
            // 丢弃老的同步帧
            var lastFrameTime = rtsServerInfo.lastFrameTime;
            if (lastFrameTime > 0 && troopPath.LastServerTime > lastFrameTime)
            {
                return;
            }
            // // 设置状态  ：fix 状态是不是应该在UpdateMonsterInfo更新
            if (marchInfo.SoldierType == 0)
            {
                marchInfo.SoldierType = monster.lod2.soldierType;
            }

            var generateNewPath = ProcessChase(rtsServerInfo, marchEntity);

            if (generateNewPath)
            {
                // 更新路径信息
                troopPath.UpdateInfo(rtsServerInfo, ref segment);
            }
          

            // 设置朝向
            if (segment.duration > 0)
            {
                marchInfo.SetForward(segment.direction);
                marchEntity.SetMarchDefaultForward(segment.direction);
            }
            else
            {
                //如果不在战斗中，则设置默认朝向
                if (rtsServerInfo.marchStatus != MarchStatus.FIGHT_2)
                {
                    marchInfo.SetForward(marchEntity.GetMarchDefaultForward(npcUid));
                }
            }
            playerBattle.OnMarchChanged(rtsServerInfo);
            marchInfo.SetServerMarchTypeAndStatus(rtsServerInfo.marchStatus,MarchType.GARRISON_2);
     
            marchEntity.Mono.transform.position = marchInfo.Position;
            k_UpdateMonsterBaseInfo.End();

            k_UpdateMonsterInfo.Begin();
            
            k_UpdateMonsterInfo1.Begin();
            var soldierCount = marchEntity.SetAndGetSoldierCountByServerSoldierList(rtsServerInfo.soldierCount,rtsServerInfo.initSoldierCount,MarchType.INIT);
            
            if (marchInfo.HeroList.Count == 0)
            {
                if (rtsServerInfo.hero1 != 0)
                {
                    marchInfo.HeroList.Add(rtsServerInfo.hero1);
                }
                if (rtsServerInfo.hero1 != 0)
                {
                    marchInfo.HeroList.Add(rtsServerInfo.hero2);
                }
                if (rtsServerInfo.hero1 != 0)
                {
                    marchInfo.HeroList.Add(rtsServerInfo.hero3);
                }
            }
            k_UpdateMonsterInfo1.End();
            k_UpdateMonsterInfo2.Begin();
            //Profiler.BeginSample("[C#]MarchManager.UpdateMarchInfo.Hud");
            if (!marchEntity.IsHudShown())
            {
                marchEntity.ShowMonsterHud(rtsServerInfo,marchContext);
            }
        
            if (marchEntity.Hud != null)
            {
                var monsterHud = marchEntity.Hud as MonsterHud;
                if (monsterHud!=null)
                {
                    monsterHud.SetEntityAndTroopData(marchEntity, rtsServerInfo);
                    monsterHud.UpdateMonsterInfo();
                }
            }
            
            JudgeSelfIsOtherTarget(marchEntity);

            k_UpdateMonsterInfo2.End();
            //Profiler.EndSample();
            k_UpdateMonsterInfo3.Begin();
            marchEntity.SetTargetId(rtsServerInfo.targetId);
            marchEntity.SetBattleTargetId(rtsServerInfo.attackTargetId,rtsServerInfo.attackTargetType);
            //Debug.Log(LogModule.RTS,$"  UpdateMonsterInfo  {npcUid}  frameCount:{Time.frameCount}  targetId:{monster.lod1.targetId}");
            // 设置阵营
            marchEntity.SetTeam(monster.lod3.team);
            k_UpdateMonsterInfo3.End();
            k_UpdateMonsterInfo4.Begin();
            // 设置状态   //TODO: 如果整理好了，这里是没必要转换的
            var clientMarchStatus = EMarchStatus.Park;
            if (rtsServerInfo.marchStatus == MarchStatus.FIGHT_2 || rtsServerInfo.marchStatus == MarchStatus.SIEGE_FIGHT_6)
            {
                clientMarchStatus = EMarchStatus.Battle;
            }
            else if (rtsServerInfo.marchStatus == MarchStatus.WALK_1)
            {
                clientMarchStatus = EMarchStatus.WALK;
            }

            #region 野怪对部队音效部分: todo: 这几天迁移到其他地方管理起来
            //todo: 这几天迁移到其他地方管理起来
            int targetIndex = -1;
            if (rtsServerInfo.attackTargetId != 0)
            {
                if (rtsEntityDictionary.TryGetValue(rtsServerInfo.attackTargetType,out var targetDiction))
                {
                    if (targetDiction.TryGetValue(rtsServerInfo.attackTargetId,out targetIndex))
                    {
                        
                    }
                }
            }
            MarchEntity targetEntity = null;
            if (targetIndex != -1)
            {
                targetEntity = marchEnitiesBase[targetIndex];
            }
            if (marchInfo.ClientMarchStatue != clientMarchStatus || (marchContext.showMarchSquare && !marchEntity.isMarchVisibleInLod))
            {
                marchEntity.SetMarchStatus(clientMarchStatus);
            }
            if (targetEntity != null)
            {
                int _team = targetEntity.RtsServerInfo.team;
                //怪物进入战斗的音效
                if (clientMarchStatus == EMarchStatus.Battle)
                {
                    if (!marchEntity.isMonsterBattleSoundDirty)
                    {
                        if (_team == (int)MarchTeam.Self && ArmyManager.Instance.CanPlayAudio(marchEntity.Team,_team))
                        {
                            AudioManager.PlaySound("sfx_rts_battle_team", marchEntity.GetAudioEmiterObject());
                            marchEntity.isMonsterBattleSoundDirty = true;
                        }
                    }
                }
                else
                {
                    if (marchEntity.isMonsterBattleSoundDirty)
                    {
                        AudioManager.StopSound("sfx_rts_battle_team", marchEntity.GetAudioEmiterObject());
                        marchEntity.isMonsterBattleSoundDirty = false;
                    }
                }
            }
            else
            {
                if (marchEntity.isMonsterBattleSoundDirty)
                {
                    AudioManager.StopSound("sfx_rts_battle_team", marchEntity.GetAudioEmiterObject());
                    marchEntity.isMonsterBattleSoundDirty = false;
                }
            }

            #endregion

            /*if (marchEntity.Hud != null)
            {

                ((MonsterHud)marchEntity.Hud)?.UpdateSoldierCount();
            }*/
            k_UpdateMonsterInfo4.End();
            k_UpdateMonsterInfo5.Begin();


            bool visible = marchInfo.NeedShowSquare() && marchContext.showMarchSquare; //方阵显示不显示是由 行军状态+lod来控制的
            //Profiler.BeginSample("[C#]MarchManager.UpdateMarchInfo.SquareVisible");
            marchEntity.UpdateSquareVisible(visible);
            marchEntity.UpdateMonsterColliderEnabled(marchContext.LodLevel);
            k_UpdateMonsterInfo5.End();
            k_UpdateMonsterInfo6.Begin();
            marchEntity.UpdateSoldierInfo(soldierCount);
            //Profiler.EndSample();
            marchEntity.SetMarchDataToSquareData();
            k_UpdateMonsterInfo6.End();
            k_UpdateMonsterInfo.End();

            if (rtsServerInfo.isFightConditionNotMet)
            {
                marchInfo.SetIsInBattle(false);
                marchInfo.SetIsClientInBattle(false);
                marchInfo.SetIsJustLeaveBattle(true);
                ((MonsterHud)marchEntity.Hud)?.ResetHudToNormalStyle();
            }

            if (forceUpdatePos)
            {
                marchEntity.Transform.position = marchEntity.MarchInfo.Position;
                marchEntity.ForceSetPosition();
            }
            //如果是奇观部队，则需要显示行军线
            var isBkArmyNpc = monster.lod3.IsBKIARMYNpc();
            var needShowMarchLine = monster.lod3.IsWonderNpc() || isBkArmyNpc; 
            if (needShowMarchLine) 
            {
                if (monster.lod3.marchStatus == MarchStatus.WALK_1)
                {
                    if (marchEntity.LineId > 0)  //删除之前的
                    {
                        RTSLuaCallCSharpManager.DelMarchLine(marchEntity.LineId);
                        marchEntity.LineId = 0;
                    }
                    if (troopPath.Points != null && troopPath.Points.Count > 0) //如果需要绘制新的，则绘制
                    {
                        var isWonderNpc = BattleUtils.IsWonderNpcBig(monster.lod3.npcType);
                        marchEntity.LineId = RTSLuaCallCSharpManager.DrawMarchLine(troopPath.Points, troopPath.SegmentIndex, marchInfo.Team, false, isWonderNpc, isBkArmyNpc);
                    }
                }
                else if (monster.lod3.marchStatus == MarchStatus.FIGHT_2)
                {
                    if (marchEntity.LineId > 0)
                    {
                        RTSLuaCallCSharpManager.DelMarchLine(marchEntity.LineId);
                        marchEntity.LineId = 0;
                    }
                }
            }
        }
        
        #endregion

        /// <summary>
        /// 根据服务器信息处理夹击的信息
        /// </summary>
        /// <param name="rtsServerInfo"></param>
        private void ProcessBesiegeInfo(RtsServerInfo rtsServerInfo)
        {
            k_MarchBesiegeManager.Begin();
            var originBesiege = rtsServerInfo.besiegeFinalAngle;
            if (rtsServerInfo.besiegeFinalAngle >= 0)//如果服务器已经给了夹角
            {
                MarchBesiegeManager.Instance.AddAttackTargetFromServer(rtsServerInfo.attackTargetUnitType,rtsServerInfo.tid,rtsServerInfo.Type,rtsServerInfo.attackTargetId,rtsServerInfo.attackTargetType,rtsServerInfo.besiegeFinalAngle);
            }
            else if (rtsServerInfo.attackTargetId > 0 && rtsServerInfo.targetId != 0 && rtsServerInfo.buildingUid == 0)
            {
                var attackTargetId = rtsServerInfo.attackTargetId;
                var attackTargetType = rtsServerInfo.attackTargetType;
                var targetMarch = GetMarchEntityByIdAndType(attackTargetId,attackTargetType);
                var isAttack = rtsServerInfo.marchType == MarchType.ATTACK_1 &&
                               rtsServerInfo.attackTargetId == rtsServerInfo.targetId;
                var isSiegeAttack = rtsServerInfo.marchType == MarchType.ATTACK_1 &&
                                    rtsServerInfo.marchStatus == MarchStatus.SIEGE_FIGHT_6;
                if (isAttack && targetMarch != null && !targetMarch.IsMoving() || rtsServerInfo.attackTargetBuildingId!=0 || isSiegeAttack)
                {
                    var position = rtsServerInfo.coordinate.ToVector3();
                    if (rtsServerInfo.pathList != null && rtsServerInfo.pathList.Length > 0)
                    {
                        position = rtsServerInfo.pathList[rtsServerInfo.pathList.Length - 1].ToVector3();
                    }

                    if (rtsServerInfo.attackTargetBuildingId!= 0)
                    {
                        attackTargetId = rtsServerInfo.attackTargetBuildingId;
                    }

                    if (rtsServerInfo.besiegeFinalAngle == -1)
                    {
                        //服务器已经走到了
                        var angle = PveUtils.GetAngleServer(Vector3.right, position - rtsServerInfo.besiegeCenter);
                        MarchBesiegeManager.Instance.AddAttackTargetFromServer(rtsServerInfo.attackTargetUnitType,rtsServerInfo.tid,rtsServerInfo.Type,rtsServerInfo.attackTargetId,rtsServerInfo.attackTargetType,angle);
                    }
                    else
                    {
                        //客户端模拟
                        MarchBesiegeManager.Instance.AddAttacker(rtsServerInfo.attackTargetUnitType,attackTargetId,attackTargetType,rtsServerInfo.tid,rtsServerInfo.targetType,position,rtsServerInfo.besiegeCenter);
                    }
                    
                }
                else
                {
                    MarchBesiegeManager.Instance.RemoveAttacker(rtsServerInfo.tid,rtsServerInfo.Type);
                }

                if (isAttack)
                {
                    MarchBesiegeManager.Instance.AddAttackTarget(rtsServerInfo.tid,rtsServerInfo.Type,rtsServerInfo.attackTargetId,rtsServerInfo.attackTargetType);
                }
                else
                {
                    MarchBesiegeManager.Instance.RemoveAttackTarget(rtsServerInfo.tid,rtsServerInfo.Type);
                }
               
            }
            else
            {
                MarchBesiegeManager.Instance.RemoveAttacker(rtsServerInfo.tid,rtsServerInfo.Type);
                MarchBesiegeManager.Instance.RemoveAttackTarget(rtsServerInfo.tid,rtsServerInfo.Type);
            }

            //如果是攻击，才会添加或维持，否则移除
            
            if (rtsServerInfo.marchType == MarchType.ATTACK_1)
            {
                //添加
                if (rtsServerInfo.marchStatus == MarchStatus.WALK_1 && rtsServerInfo.targetId != 0 &&
                    rtsServerInfo.pathList != null && rtsServerInfo.pathList.Length > 0)
                {
                    //计算到达的时间
                    var startTime = rtsServerInfo.lastFrameTime;
                    long time = 0;
                    var d = 0f;
                    var position = rtsServerInfo.pathList[0];
                    for (int i = 0; i < rtsServerInfo.pathList.Length; i++)
                    {
                        d += BattleUtils.Distance(position, rtsServerInfo.pathList[i]);
                        position = rtsServerInfo.pathList[i];
                    }
                    time = (long)(d / (rtsServerInfo.speed / 3600f) * 1000);
                    MarchBesiegeManager.Instance.AddReachTime(rtsServerInfo.tid,rtsServerInfo.Type,rtsServerInfo.targetId,rtsServerInfo.targetType,startTime + time);
                }
                //维持
            }
            else
            {
                MarchBesiegeManager.Instance.RemoveReachTime(rtsServerInfo.tid,rtsServerInfo.Type);
            }
            k_MarchBesiegeManager.End();
        }

        /// <summary>
        /// 根据服务器信息处理攻防关系
        /// </summary>
        /// <param name="rtsServerInfo"></param>
        private void ProcessPlayerBattleRelation(RtsServerInfo rtsServerInfo)
        {
            // 绑定玩家和行军的关系
//            k_UpdateTroopMarchInfo3.Begin();
            if (!marchToPlayer.ContainsKey(rtsServerInfo.tid))
            {
                AddPlayer2March(rtsServerInfo.tid,rtsServerInfo.Type,rtsServerInfo.playerId);
                playerBattle.OnMarchAdded(rtsServerInfo);
            }
            
            playerBattle.OnMarchChanged(rtsServerInfo);

//            k_UpdateTroopMarchInfo3.End();
        }

        private void ProcessPlayerBattleRelationCommonObj(RtsServerInfo rtsServerInfo)
        {
            if (rtsServerInfo.Type == TargetCoordinateType.DEFENCE_ASSEMBLY_NPC_23 || rtsServerInfo.Type == TargetCoordinateType.DEFENSE_ASSEMBLY_29)
            {
                var playerId = -1;
                if (!marchToPlayer.ContainsKey(rtsServerInfo.tid))
                {
                    AddPlayer2March(rtsServerInfo.tid,rtsServerInfo.Type,playerId);
                    playerBattle.OnMarchAdded(rtsServerInfo);
                }
                playerBattle.OnMarchChanged(rtsServerInfo);
            }
        }
        /// <summary>
        /// 处理渲染用的士兵和英雄信息
        /// </summary>
        /// <param name="rtsServerInfo"></param>
        /// <param name="marchEntity"></param>
        private int ProcessSoldierHeroInfo(RtsServerInfo rtsServerInfo,MarchEntity marchEntity)
        {
            MarchInfo marchInfo = marchEntity.MarchInfo;
            marchInfo.SoldierListLength = rtsServerInfo.SoldierListLength;
            
            if (rtsServerInfo.soldierListAccess !=null && rtsServerInfo.soldierListAccess.IsValid())
            {
                marchInfo.soldierListAccess = rtsServerInfo.soldierListAccess;
            }
            
            //先初始化数据,再初始化HUD一类的,之前出现了
            if (marchInfo.SoldierType == 0)
            {
                marchInfo.SoldierType = rtsServerInfo.SoldierType;
            }

            if (marchInfo.MaxRage == 0 && rtsServerInfo.MaxRage > 0)
            {
                marchInfo.MaxRage = rtsServerInfo.MaxRage;
            }
            
            // Step02: 更新显示小兵&英雄： 确定要显示那些小兵的id
            var soldierCount = marchEntity.SetAndGetSoldierCountByServerSoldierList(rtsServerInfo.soldierCount,rtsServerInfo.initSoldierCount,rtsServerInfo.marchType); //当soldierList为空也要传入，里面在侦察和死亡后也有显示
            
            bool heroChanged = false;
            // 设置英雄列表
            if (marchInfo.HeroList.Count > 0)
            {
                for (int i = 0; i < 3; i++)
                {
                    var id = rtsServerInfo.hero1;
                    if (i == 1)
                    {
                        id = rtsServerInfo.hero2;
                    }
                    else if (i == 2)
                    {
                        id = rtsServerInfo.hero3;
                    }
                    if (marchInfo.HeroList.Count <= i || id != marchInfo.HeroList[i])
                    {
                        heroChanged = true;
                        break;
                    }
                }

                if (heroChanged)
                {
                    marchInfo.HeroList.Clear();
                    marchInfo.HeroQualityList.Clear();
                    marchInfo.HeroRageList.Clear();
                }
            }
            if (marchInfo.HeroList.Count == 0)  //英雄列表不会变，所以不用重复赋值
            {
                if (rtsServerInfo.hero1 != 0)
                {
                    marchInfo.HeroList.Add(rtsServerInfo.hero1);
                }
                if (rtsServerInfo.hero2 != 0)
                {
                    marchInfo.HeroList.Add(rtsServerInfo.hero2);
                }
                if (rtsServerInfo.hero3 != 0)
                {
                    marchInfo.HeroList.Add(rtsServerInfo.hero3);
                }
            }
            if (marchInfo.HeroQualityList.Count == 0 && rtsServerInfo.heroQualityList != null && rtsServerInfo.heroQualityList.Length > 0)
            {
                marchInfo.HeroQualityList.AddRange(rtsServerInfo.heroQualityList);
            }
            
            if(marchInfo.HeroRageList.Count == 0 && rtsServerInfo.heroRageList != null)
            {
                marchInfo.HeroRageList.AddRange(rtsServerInfo.heroRageList);
            }

            if (heroChanged)
            {
                marchEntity.SetHeroIcon(rtsServerInfo);
                marchEntity.OnHeroChanged();
            }
            return soldierCount;
        }
        
        /// <summary>
        /// 创建部队UI
        /// </summary>
        /// <param name="rtsServerInfo"></param>
        /// <param name="marchEntity"></param>
        private void ProcessCreateTroopHud(RtsServerInfo rtsServerInfo,MarchEntity marchEntity)
        {
            // 新部队，创建HUD
            if (!marchEntity.IsHudShown())
            {
                if (!rtsServerInfo.visible)
                {
                    return;
                }
                if (rtsServerInfo.Type == TargetCoordinateType.CARGO_TRUCK_42)
                {
                    marchEntity.ShowCargoTruckHud(rtsServerInfo, marchContext);
                    return;
                }

                marchEntity.ShowMarchHud(rtsServerInfo, marchContext);
                var marchHud = marchEntity.Hud;
                //TODO:待优化
                if (!marchEntity.isFakeChild && !marchEntity.isClientCreateMarch())
                {
                    if (L_BindHudToMarchDataFunc == null)
                    {
                        L_BindHudToMarchDataFunc = LuaManager.mainState.GetFunction("G_MarchManager.BindHudToMarchData");
                    }
                    L_BindHudToMarchDataFunc.Action(marchHud.Lod0, marchHud.Lod1, rtsServerInfo.tid,(int)rtsServerInfo.Type,rtsServerInfo.team,rtsServerInfo.playerName);
                }
            }
            else
            {
                marchEntity.SetHeroIcon(rtsServerInfo);
                
                if (rtsServerInfo.Type == TargetCoordinateType.MARCH_3)
                {
                    marchEntity.SetPlayerTitle();
                }
                
                if (rtsServerInfo.marchStatus == MarchStatus.FIGHT_2)
                {
                    marchEntity.MarchInfo.FightFrameTime = clientTime;
                }
            }
        }

        
        private void ProcessSetMarchEntityInfoFromServerInfo(RtsServerInfo rtsServerInfo,MarchEntity marchEntity)
        {
            MarchInfo marchInfo = marchEntity.MarchInfo;
            marchEntity.SetTargetId(rtsServerInfo.targetId);
            if (!marchEntity.isFakeParent)
            {
                marchEntity.SetBattleTargetId(rtsServerInfo.attackTargetId,rtsServerInfo.attackTargetType);
            }
            marchInfo.SetTargetPosition(rtsServerInfo.targetPosition);
            marchInfo.SetTargetType(rtsServerInfo.targetType,rtsServerInfo.attackTargetType);
            marchInfo.SetServerMarchTypeAndStatus(rtsServerInfo.marchStatus, rtsServerInfo.marchType);
            marchEntity.MarchInfo.BuildingUid = rtsServerInfo.buildingUid;
            marchEntity.SetTeam(rtsServerInfo.team);
            marchEntity.Radius = BattleUtils.GetRadius(0);
        }
        
        /// <summary>
        /// 处理部队行军线相关逻辑
        /// </summary>
        private void ProcessTroopPath(RtsServerInfo rtsServerInfo,MarchEntity marchEntity,ref Segment segment,TroopPath troopPath, bool isForceRefresh = false)
        {
            //判断是否需要预判一个夹击位，提前移动
            marchEntity.CheckNeedCalculateBesiegeAngle(rtsServerInfo);
            //判断是否是夹击，如果是的话需要客户端生成路点
            marchEntity.CheckNeedGenerateBesiegePathList(rtsServerInfo);
            bool generateNewPath = true;
            //判断是否需要追击
            generateNewPath = ProcessChase(rtsServerInfo, marchEntity);

            if (generateNewPath)
            {
                // Step01: 更新部队位置&朝向； 否则后面位置数据不对
                troopPath.UpdateInfo(rtsServerInfo, ref segment,marchEntity.MarchInfo.ClientMarchStatue == EMarchStatus.CrossingGate || isForceRefresh);
            }
            
            marchEntity.MarchInfo.IsForceMoveChild = troopPath.IsForceMoveChild;
            if (!marchEntity.InitPos)
            {
                marchEntity.InitPos = true;
            }
            if (segment.duration > 0)
            {
                marchEntity.MarchInfo.SetForward(segment.direction);
                marchEntity.SetMarchDefaultForward(segment.direction);
            }
            else
            {
                if (marchEntity.defaultForward != default && rtsServerInfo.garrisonAngle == 0)
                {
                    
                }
                else
                {
                    marchEntity.SetMarchDefaultForward(BattleUtils.GetServerForward(rtsServerInfo.garrisonAngle));
                }
                //如果不在战斗中，则设置默认朝向
                if (rtsServerInfo.marchStatus != MarchStatus.FIGHT_2 && ! marchEntity.MarchInfo.IsInBattleState)
                {
                    //判断一下，角度是否差距过小
                    if (marchEntity.Forward != Vector3.zero && Vector3.Angle(marchEntity.Forward, marchEntity.defaultForward) < 10)
                    {
                        
                    }
                    else
                    {
                        marchEntity.MarchInfo.SetForward(marchEntity.defaultForward);
                    }
                    
                }
            }
            
            //计算部队攻击范围
            var attRange = rtsServerInfo.attRange;

            segment.setAttackRange(attRange);
            
            
            if (troopPath.NeedUpdateLine) 
            {
                troopPath.NeedUpdateLine = false;
                if (marchEntity.LineId > 0)  //删除之前的
                {
                    RTSLuaCallCSharpManager.DelMarchLine(marchEntity.LineId);
                    marchEntity.LineId = 0;
                }
                if(troopPath.Points!=null && troopPath.Points.Count>0 && rtsServerInfo.visible ) //如果需要绘制新的，则绘制
                {
                    //如果是竞技场的地方部队，不显示
                    if (marchEntity.isArenaMarch && marchEntity.Team != 0)
                    {
                        return;
                    }

                    if (marchEntity.isExpeditionMarchMoving)
                    {
                        return;
                    }

                    if (isShowTroopLine(marchEntity))
                    {
                        marchEntity.LineId = RTSLuaCallCSharpManager.DrawMarchLine(troopPath.Points, troopPath.SegmentIndex, rtsServerInfo.team,rtsServerInfo.Type == TargetCoordinateType.ASSEMBLY_20);
                    }
                }
            }

//            k_UpdateTroopMarchBaseInfo2.End();
        }

        private void ProcessClientStatus(RtsServerInfo rtsServerInfo,MarchEntity marchEntity,bool isMarchTypeChanged,int soldierCount,TroopPath troopPath)
        {
            var marchInfo = marchEntity.MarchInfo;
            var beforeMarchStatus = marchInfo.ClientMarchStatue;
            var clientMarchStatus = GetClientMarchType(rtsServerInfo);
            if (clientMarchStatus == EMarchStatus.Collect)
            {
                marchEntity.Radius = BattleUtils.GetRadius(1);
            }
            if (marchInfo.ClientMarchStatue != clientMarchStatus || isMarchTypeChanged)
            {
                PlayerBattleSound(clientMarchStatus, marchInfo.ClientMarchStatue, rtsServerInfo.targetType, oldTargetType, marchEntity.GetAudioEmiterObject(), marchEntity.Tid, rtsServerInfo.team,rtsServerInfo.targetTeam,marchEntity);
//                k_UpdateTroopMarchInfo7.Begin();
                marchEntity.SetMarchStatus(clientMarchStatus);
//                k_UpdateTroopMarchInfo7.End();
                if (marchInfo.ClientMarchStatue == EMarchStatus.CrossingGate)
                {
                    var needShowTransition = beforeMarchStatus != EMarchStatus.Uninit;
                    marchInfo.StartCrossingGate(!needShowTransition);
                    marchInfo.UpdateCrossingGate();
                    marchInfo.IsForceMoveChild = true;
                    //开始过桥表现
                    marchEntity.StartCrossingGate(needShowTransition);
                }
            }
            
            var isPveAssembleDismissed = MarchHelper.IsPveAssembleDismissed(rtsServerInfo);
            if (!isPveAssembleDismissed || rtsServerInfo.marchType != marchInfo.MarchType)
            {
                marchEntity.EndFakeMoveForward();
            }
            marchEntity.UpdateSoldierInfo(soldierCount);
            
            if (clientMarchStatus == EMarchStatus.Escape)
            {
                marchEntity.UpdateEscapeInfo();
                marchEntity.SetMarchStatus(clientMarchStatus);
            }
            _roundFightPlayer.OnChangedEffect(rtsServerInfo.tid,rtsServerInfo.Type);
            oldTargetType = rtsServerInfo.targetType;

            if (rtsServerInfo.marchStatus == MarchStatus.FIGHT_2 && troopPath != null)
            {
                marchEntity.isServerPosChange = troopPath.isServerPosChange;
                //Debug.Log($"UpdateTroopMarchInfo  isServerPosChange:{marchEntity.isServerPosChange}  {troopId}   frameCount： {Time.frameCount}  serverPos: {troopPath.ServerPosition}");
            }

            marchEntity.StopReadyToHide();
            if (isPveAssembleDismissed)
            {
                Vector3 targetForward;
                Vector3 startPosition;
                //尝试拿集结部队
                var assemblyEntity = GetMarchEntityByIdAndType(rtsServerInfo.leavePveAssemblyId,
                    com.youzu.warh.protocol.TargetCoordinateType.ASSEMBLY_20);
                if (assemblyEntity != null)
                {
                    startPosition = assemblyEntity.MarchInfo.Position;
                }
                else
                {
                    startPosition = new Vector3(rtsServerInfo.coordinate.xAxis, 0, rtsServerInfo.coordinate.zAxis);
                }
                if (assemblyEntity != null && (assemblyEntity.MarchInfo.ClientMarchStatue == EMarchStatus.Battle || assemblyEntity.IsMoving())) 
                {
                    targetForward = -assemblyEntity.Forward.normalized;
                }
                else
                {
                    targetForward = MarchHelper.GetRandomForward();
                }
                
                var targetPosition = startPosition + targetForward * 3;
                //UnityEngine.Debug.LogError(rtsServerInfo.tid + " " + startPosition + " " + targetPosition + " " + marchInfo.Speed);
                marchEntity.UpdateSquareVisible(true);
                marchEntity.FakeMoveForward(startPosition,targetPosition);
                marchEntity.ReadyToHide();
            }
        }


        private void ProcessTroopVisible(RtsServerInfo rtsServerInfo, MarchEntity marchEntity,Vector3 lastPosition,int soldierCount)
        {
            var marchInfo = marchEntity.MarchInfo;
            //Step02: 设置部队是否需要显示出来(创建、隐藏）
            bool isChangedVisible = marchInfo.SetTroopStateVisible(rtsServerInfo.visible) || marchInfo.marchSquareVisibleDirty;
            bool visible = marchInfo.NeedShowSquare() && marchContext.showMarchSquare; //方阵显示不显示是由 行军状态+lod来控制的
            if (isChangedVisible)
            {
                marchInfo.marchSquareVisibleDirty = false;
                
                //如果是进建筑
                bool shouldHide = !visible && marchEntity.ClientMarchType != EClientMarchType.Scout && marchEntity.ClientMarchType != EClientMarchType.Rescue &&
                                (rtsServerInfo.marchStatus == MarchStatus.REMOVE_4 ||
                                (rtsServerInfo.marchType == MarchType.AID_8 && rtsServerInfo.buildingUid > 0));
                if (shouldHide)
                {
                    marchEntity.FakeMoveForward(lastPosition,new Vector3(rtsServerInfo.coordinate.xAxis,0,rtsServerInfo.coordinate.zAxis));
                    if (marchEntity.MarchInfo.IsForceMoveChild)
                    {
                        marchEntity.MarchInfo.IsForceMoveChild = false;
                    }
                }
                marchEntity.UpdateSquareVisible(visible);
            }
            else
            {
                marchEntity.CheckNeedResetChildrenNum(soldierCount);
                marchEntity.CheckNeedResetMarchSkin(marchEntity.RtsServerInfo.marchSkinResId);
            }
        }

        private bool ProcessChase(RtsServerInfo rtsServerInfo,MarchEntity marchEntity)
        {
            var generateNewPath = true;
            if (!marchEntity.isArenaMarch && rtsServerInfo.attackTargetId > 0 && rtsServerInfo.targetId != 0 &&
                rtsServerInfo.marchType == MarchType.ATTACK_1 && marchEntity.InitPos)
            {
                var attackTargetId = rtsServerInfo.attackTargetId;
                var attackTargetType = rtsServerInfo.attackTargetType;
                var targetMarch = GetMarchEntityByIdAndType(attackTargetId, attackTargetType);
                if (targetMarch != null && targetMarch.MarchInfo.SoldierCount > 0)
                {
                    var path = targetMarch.RtsServerInfo.pathList;
                    //目标是否在移动（有路点）
                    if (path != null && path.Length > 0)
                    {
                        //判断我自己是否有路点，路点是否可靠
                        var isPathValid = true;
                        var selfPath = rtsServerInfo.pathList;
                        if (selfPath == null || selfPath.Length <= 1)
                        {
                            isPathValid = false;
                        }
                        else
                        {
                            var distance = BattleUtils.Distance(selfPath[1], rtsServerInfo.coordinate);
                            var distancePerSecond = rtsServerInfo.speed / 3600 * 1;
                            if (distance < distancePerSecond)
                            {
                                isPathValid = false;
                                //追击过程中的路点，客户端认为无效
                            }
                        }
                        
                        if (!isPathValid)
                        {
                            rtsServerInfo.pathList = null;
                            updateChaseList.Add(marchEntity);
                            generateNewPath = false;
                        }
                    }
                }
            }

            return generateNewPath;
        }
        
        /// <summary>
        /// 因时序问题，目标部队可能没有创建 遂建立一个缓存关系等待对方创建后 更新一些逻辑
        /// </summary>
        /// <param name="targetId"></param>
        /// <param name="targetType"></param>
        /// <param name="sourceId"></param>
        [BlackList]
        public void RegistTargetIdFindSourceTroop(long targetId,TargetCoordinateType targetType,long sourceId,TargetCoordinateType sourceType)
        {
//            _listPool
            var troop = new Troop(targetId,targetType);
            if (!targetIdAndSourceIdMap.TryGetValue(troop,out var list))
            {
                list = _listPool.GetItem();
                targetIdAndSourceIdMap.Add(troop,list);
            }

            var sourceTroop = new Troop(sourceId, sourceType);

            if (!list.Contains(sourceTroop))
            {
                list.Add(sourceTroop);
            }
        }

        /// <summary>
        /// 判断该部队是否是别人的攻击目标（因时序问题可能导致的部队目标获取不到）如果是，重新跑下方向等逻辑
        /// </summary>
        /// <param name="entity"></param>
        [BlackList]
        public void JudgeSelfIsOtherTarget(MarchEntity entity)
        {
            if (targetIdAndSourceIdMap.TryGetValue(new Troop(entity.Tid,entity.TargetCoordinateType), out var list))
            {
                foreach (var troop in list)
                {
                    var targetEntity = GetMarchEntityByIdAndType(troop.Uid,troop.Type);
                    if (targetEntity != null)
                    {
                        var forward = targetEntity.MarchInfo.GetTargetPosition() - targetEntity.MarchInfo.Position;
                        targetEntity.SetForward(forward);
                        playerBattle.OnMarchChanged(targetEntity.RtsServerInfo);
                    }
                }

                _listPool.RecoverItem(list);
                list.Clear();
                targetIdAndSourceIdMap.Remove(new Troop(entity.Tid,entity.TargetCoordinateType));
            }
        }
        
        [LuaCallCSharp]
        public MarchEntity UpdateMapCommonBattleObj(MapCommonBattleObj commonObj,int type,LuaArrAccess access,long fakeParentId = -1)
        {
            MarchEntity marchEntity;
            
            if (!rtsEntityDictionary.TryGetValue((TargetCoordinateType)type,out var dictionary))
            {
                dictionary = new Dictionary<long, int>();
                rtsEntityDictionary.Add((TargetCoordinateType)type,dictionary);
            }

            var uid = commonObj.identity.uid;
            if (fakeParentId > 0)
            {
                uid = fakeParentId;
            }
            
            if (!dictionary.ContainsKey(uid))
            {
                marchEntity = GetMarchEntityFromPool(false);
                marchEntity.Initialize(uid,(int)MarchTeam.Enemy,EClientMarchType.Common,(TargetCoordinateType)type);
                var go = marchEntity.GetGameObject();

                MarchMono res = go.GetComponent<MarchMono>();
                res.Init(marchEntity.ClientMarchType,marchEntity.Tid,(TargetCoordinateType)type,false);
                
#if UNITY_EDITOR
                go.name = string.Format("MapCommonBattleObj-{0}-{1}",type,uid);
#endif
                marchEnitiesBase.Add(marchEntity);
                if (marchEntity.AudioEmitter == null)
                {
                    marchEntity.AudioEmitter = res.marchAudioEmitter?.AddComponent<AudioEmitter3D>();
                    marchEntity.AudioEmitter.UpdateFrequency = UpdateFrequency.Low; //low是每9fps更新一次位置，应该够用了
                }
                else
                {
                    marchEntity.AudioEmitter.enabled = true;
                }
                marchEntity.MarchManager = this;
                marchEntity.MarchInfo.MarchIndex = count;
                if (marchEntity.TargetCoordinateType == TargetCoordinateType.DONALD_BOSS_38)
                {
                    marchEntity.SetForward(new Vector3(-0.7f,0,-0.7f));
                }
                else
                {
                    marchEntity.SetForward(-Vector3.forward);
                }
                var troopPath = ClassManager.Get<TroopPath>();
                paths.Add(troopPath);
                
                dictionary[uid] = count;
                count++;
            }
            else
            {
                var key = dictionary[uid];
                marchEntity = marchEnitiesBase[key];
            }

            var rtsServerInfo = RtsConvertDataFactory.ConvertData(commonObj, marchEntity.RtsServerInfo,access);
            if (marchEntity.RtsServerInfo == null)
            {
                marchEntity.RtsServerInfo = rtsServerInfo;
            }

            var coordinate = rtsServerInfo.coordinate;
            marchEntity.MarchInfo.Coordinate = new Vector3(coordinate.xAxis, 0, coordinate.zAxis);

            marchEntity.Transform.position = marchEntity.MarchInfo.Position;

           
            JudgeSelfIsOtherTarget(marchEntity);
            ProcessSoldierHeroInfo(rtsServerInfo,marchEntity);
            bool visible = marchEntity.MarchInfo.NeedShowSquare() && marchContext.showMarchSquare; //方阵显示不显示是由 行军状态+lod来控制的
            marchEntity.UpdateSquareVisible(visible);
            marchEntity.UpdateSoldierInfo();
            ProcessTroopVisible(rtsServerInfo, marchEntity, marchEntity.Position,rtsServerInfo.soldierCount);

            bool showHud = true;
            if (fakeParentId == 0 || type == (int)TargetCoordinateType.DONALD_BOSS_38)
            {
                //如果是桥梁父节点，则不显示hud
                showHud = false;
            }
            
            if (!marchEntity.IsHudShown() && showHud)
            {
                if (type == (int)TargetCoordinateType.ALLIANCE_PRACTICE_BOSS_32)
                {
                    bool? isShow = IsMyAlliance?.Func<long, bool>(rtsServerInfo.alliandeId);
                    if (isShow.HasValue && isShow.Value)
                    {
                        marchEntity.ShowPractiseBossHud(rtsServerInfo, marchContext);
                    }
                }
                else if(type == (int)TargetCoordinateType.WORLD_BOSS_44)
                {
                    marchEntity.ShowWorldBossHud(rtsServerInfo, marchContext);
                }
                else if (type == (int)TargetCoordinateType.SMUGGLER_30)
                {
                    marchEntity.ShowSmugglerHud(rtsServerInfo, marchContext);
                }
                else
                {
                    marchEntity.ShowMarchHud(rtsServerInfo, marchContext);
                }
            }

            if (rtsServerInfo.Type == TargetCoordinateType.SMUGGLER_30)
            {
                if (marchEntity.Hud != null)
                {
                    var monsterHud = marchEntity.Hud as MonsterHud;
                    if (monsterHud != null)
                    {
                        monsterHud.SetEntityAndTroopData(marchEntity, rtsServerInfo);
                        monsterHud.UpdateMonsterInfo();
                    }
                }
                marchEntity.SmuggleEntityUpdate();
            }
            if (fakeParentId != 0)
            {
                ProcessPlayerBattleRelationCommonObj(rtsServerInfo);
            }
            bool isMarchTypeChanged = rtsServerInfo.marchType != marchEntity.MarchInfo.MarchType;
            ProcessSetMarchEntityInfoFromServerInfo(rtsServerInfo, marchEntity);
            
            ProcessClientStatus(rtsServerInfo,marchEntity,isMarchTypeChanged,rtsServerInfo.soldierCount,null);

            
            if (fakeParentId >= 0)
            {
                ProcessFakeParent(uid,fakeParentId,marchEntity);
            }
            return marchEntity;
        }


        [LuaCallCSharp]
        public void removeMapCommonBattleObj(long uid,int type)
        {
            DestroyMarch(uid,type);
        }

        private Dictionary<long, Dictionary<long, Coordinate>> checkPointAnnexBuildings =
            new Dictionary<long, Dictionary<long, Coordinate>>();

        public Dictionary<long, MarchEntity> fakeTroopParents = new Dictionary<long, MarchEntity>();
        private Dictionary<int,Dictionary<long, long>> fakeTroopParentChildMatch = new Dictionary<int,Dictionary<long, long>>();
        private Dictionary<int,Dictionary<long, Coordinate>> fakeTroopCoordinate = new Dictionary<int,Dictionary<long, Coordinate>>();

        [LuaCallCSharp]
        public void UpdateCheckPointAnnexBuilding(long checkPointId, long uid, Coordinate coordinate)
        {
            if (!checkPointAnnexBuildings.TryGetValue(checkPointId, out var checkPoint))
            {
                checkPoint = new Dictionary<long, Coordinate>();
                checkPointAnnexBuildings.Add(checkPointId,checkPoint);
            }
            checkPoint[uid] = coordinate;
        }

        public void RemoveCheckPointAnnexBuilding(long checkPointId)
        {
            checkPointAnnexBuildings.Remove(checkPointId);
        }

        [LuaCallCSharp]
        public void UpdateCheckPointFakeTroopMatch(int type,long parentId,long childId,Coordinate coordinate)
        {
            if (!fakeTroopParentChildMatch.TryGetValue(type, out var match))
            {
                match = new Dictionary<long, long>();
                fakeTroopParentChildMatch.Add(type,match);
            }
            match[childId] = parentId;
            if (!fakeTroopCoordinate.TryGetValue(type, out var coord))
            {
                coord = new Dictionary<long, Coordinate>();
                fakeTroopCoordinate.Add(type,coord);
            }
            coord[childId] = coordinate;
        }

        public void RemoveFakeChildren(int type,long childId)
        {
            if (fakeTroopParentChildMatch.TryGetValue(type, out var march))
            {
                march.Remove(childId);
            }

            if (fakeTroopCoordinate.TryGetValue(type, out var coord))
            {
                coord.Remove(childId);
            }
        }

        public void RemoveFakeParent(int type, long parentId)
        {
            fakeTroopParents.Remove(parentId);
        }
        
        public void UpdateFakeTroopMarch(long parentId,long childId,TargetCoordinateType type)
        {
            var parent = GetMarchEntityByIdAndType(parentId, type);
            if (parent != null)
            {
                parent.SetIsFakeParent();
                
                if (!rtsEntityDictionary.TryGetValue((TargetCoordinateType)type,out var dictionary))
                {
                    dictionary = new Dictionary<long, int>();
                    rtsEntityDictionary.Add((TargetCoordinateType)type,dictionary);
                }

                MarchEntity marchEntity;
                var uid = childId;
                
                if (!dictionary.ContainsKey(uid))
                {
                    marchEntity = GetMarchEntityFromPool(true);
                    marchEntity.Initialize(uid,(int)MarchTeam.Enemy,EClientMarchType.Common,(TargetCoordinateType)type);
                    var go = marchEntity.GetGameObject();

                    MarchMono res = go.GetComponent<MarchMono>();
                    res.Init(marchEntity.ClientMarchType,marchEntity.Tid,(TargetCoordinateType)type);
         
    #if UNITY_EDITOR
                    go.name = string.Format("MapFakeTroop-{0}-{1}",type,uid);
    #endif
                    marchEnitiesBase.Add(marchEntity);
                
                    marchEntity.MarchManager = this;
                    marchEntity.MarchInfo.MarchIndex = count;
                    
                    var troopPath = ClassManager.Get<TroopPath>();
                    paths.Add(troopPath);
                    
                    dictionary[uid] = count;
                    count++;
                }
                else
                {
                    var key = dictionary[uid];
                    marchEntity = marchEnitiesBase[key];
                }
                parent.AddFakeChild(marchEntity);

                marchEntity.isFakeChild = true;
                var rtsServerInfo = marchEntity.RtsServerInfo;
                if (marchEntity.RtsServerInfo == null)
                {
                    marchEntity.RtsServerInfo = rtsServerInfo;
                }
            
                JudgeSelfIsOtherTarget(marchEntity);
                if (fakeTroopCoordinate.TryGetValue((int)type,out var coord))
                {
                    if (coord.TryGetValue(uid,out var coordinate))
                    {
                        marchEntity.MarchInfo.Coordinate = new Vector3(coordinate.xAxis, 0, coordinate.zAxis);
                    }
                }

                ProcessSoldierHeroInfo(rtsServerInfo,marchEntity);
                
                /*if (!marchEntity.IsHudShown())
                {
                    marchEntity.ShowMarchHud(rtsServerInfo,marchContext);
                }*/
                bool isMarchTypeChanged = rtsServerInfo.marchType != marchEntity.MarchInfo.MarchType;
                ProcessSetMarchEntityInfoFromServerInfo(rtsServerInfo, marchEntity);
                
                ProcessClientStatus(rtsServerInfo,marchEntity,isMarchTypeChanged,rtsServerInfo.soldierCount,null);
            }
        }

        public void AddToChaseList(MarchEntity entity)
        {
            updateChaseList.Add(entity);
        }
        private int battleSoundCount;
        private int cityBattleSoundCount;
        private Dictionary<long, GameObject> BattleTroopsDic = new Dictionary<long, GameObject>(50);
        private Dictionary<long, GameObject> CityBattleTroopsDic = new Dictionary<long, GameObject>(50);
        private Dictionary<long, int> IsPlayingSoundDic = new Dictionary<long, int>(30);
        private void PlayerBattleSound(EMarchStatus clientMarchStatus, EMarchStatus beforeMarchStatus,
            TargetCoordinateType lod2TargetType, TargetCoordinateType beforeTargetType,
             GameObject obj, long marchEntityTid,int marchTeam,int targetTeam,MarchEntity entity)
        {
            if (!ArmyManager.Instance.CanPlayAudio(marchTeam,targetTeam))
            {
                return;
            }
            k_PlayerBattleSound.Begin();
            if (clientMarchStatus == EMarchStatus.Battle || clientMarchStatus == EMarchStatus.Chasing || clientMarchStatus == EMarchStatus.Besiege)
            {
//                Debug.LogError("tid   " + marchEntityTid + "clientMarchStatus   " + clientMarchStatus);
                if (lod2TargetType != TargetCoordinateType.CASTLE_2)
                {
                    if (battleSoundCount < 2 && battleSoundCount >= 0)
                    {
                        battleSoundCount++;
                    }

                    if (!BattleTroopsDic.ContainsKey(marchEntityTid))
                    {
                        BattleTroopsDic.Add(marchEntityTid, obj);
                    }
                }
                else
                {
                    if (cityBattleSoundCount < 2 && cityBattleSoundCount >= 0)
                        cityBattleSoundCount++;

                    if (!CityBattleTroopsDic.ContainsKey(marchEntityTid))
                    {
                        CityBattleTroopsDic.Add(marchEntityTid, obj);
                    }
                }
                
            }
            else
            {
//                Debug.LogError("tid   " + marchEntityTid + "beforeMarchStatus   " + beforeMarchStatus);
                /*if (beforeMarchStatus == EMarchStatus.Battle|| beforeMarchStatus == EMarchStatus.Chasing || beforeMarchStatus == EMarchStatus.Besiege)
                {*/
                    if (IsPlayingSoundDic.ContainsKey(marchEntityTid))
                    {
                        if (BattleTroopsDic.ContainsKey(marchEntityTid))
                        {
                            //CheckStopSelfBattle(marchTeam,targetTeam);
                            AudioManager.StopSound("sfx_rts_battle_team", entity.GetAudioEmiterObject());
                            entity.isMonsterBattleSoundDirty = false;
                            BattleTroopsDic.Remove(marchEntityTid);
                        }

                        if (CityBattleTroopsDic.ContainsKey(marchEntityTid))
                        {
                            //CheckStopSelfBattle(marchTeam,targetTeam);
                            AudioManager.StopSound("sfx_rts_battle_wall", CityBattleTroopsDic[marchEntityTid]);
                            CityBattleTroopsDic.Remove(marchEntityTid);
                        }
                        IsPlayingSoundDic.Remove(marchEntityTid);
                    }
                /*}*/
            }

            foreach (var battleTroop in BattleTroopsDic)
            {
                var key = battleTroop.Key;
                if (!IsPlayingSoundDic.ContainsKey(key))
                {
                    AudioManager.PlaySound("sfx_rts_battle_team", entity.GetAudioEmiterObject());
                    entity.isMonsterBattleSoundDirty = true;
                    IsPlayingSoundDic.Add(key, 1);
                }
            }
            foreach (var cityTroops in CityBattleTroopsDic)
            {
                var key = cityTroops.Key;

                if (!IsPlayingSoundDic.ContainsKey(key))
                {
                    AudioManager.PlaySound("sfx_rts_battle_wall", cityTroops.Value);
                    IsPlayingSoundDic.Add(key, 2);
                }
            }
            
            k_PlayerBattleSound.End();
        }
        private void StopPlayAudio(long marchEntityTid,int marchTeam,int targetTeam,MarchEntity entity)
        {
            if (IsPlayingSoundDic.ContainsKey(marchEntityTid))
            {
                if (IsPlayingSoundDic[marchEntityTid] == 1)
                {
                    AudioManager.StopSound("sfx_rts_battle_team", entity.GetAudioEmiterObject());
                    entity.isMonsterBattleSoundDirty = false;
                    IsPlayingSoundDic.Remove(marchEntityTid);
                    BattleTroopsDic.Remove(marchEntityTid);
                }
                else
                {
                    AudioManager.StopSound("sfx_rts_battle_wall", null, 1);
                    IsPlayingSoundDic.Remove(marchEntityTid);
                    CityBattleTroopsDic.Remove(marchEntityTid);
                }
            }
        }

        public void StopAllBattleAudio()
        {
            if (IsPlayingSoundDic != null)
            {
                var enumerator = IsPlayingSoundDic.GetEnumerator();

                while (enumerator.MoveNext())
                {
                    var value = enumerator.Current.Value;
                    if (value == 1)
                    {
                        AudioManager.StopSound("sfx_rts_battle_team", null, 1);
                    }
                    else
                    {
                        AudioManager.StopSound("sfx_rts_battle_wall", null, 1);
                    }
                }

                enumerator.Dispose();
                
                IsPlayingSoundDic.Clear();
            }
        }

        /// <summary>
        /// 检查是否是自己部队开始战斗触发
        /// </summary>
        private void CheckStartSelfBattle(int marchTeam, int targetTeam)
        {
            if (marchTeam == (int)MarchTeam.Self || targetTeam == (int)MarchTeam.Self)
            {
                WorldEntry.instance?.PlayBattleBackMusic();
            }
        }

        /// <summary>
        /// 检查是否是自己部队结束战斗触发
        /// </summary>
        public void CheckStopSelfBattle(int marchTeam,int targetTeam)
        {
            if (!ArmyManager.Instance.IsInSandBox)
            {
                return;
            }
            if (marchTeam == (int)MarchTeam.Self || targetTeam == (int)MarchTeam.Self)
            {
                WorldEntry.instance?.PlayNormalBackMusic();
            }
        }

        private IEnumerator WaitForSecond(float second, Action action)
        {
            yield return new WaitForSeconds(second);

            action?.Invoke();
        }

        
        private bool UpdateMarchContext()
        {
            if (mainCameraTransform == null)
            {
                return false;
            }
            bool isUpdateCameraPos = false;
            var worldEntry = DynamicLayerMgr.worldEntry;
            var isCameraChanged = false;
            var lodLevel = 1;
            var lodPercent = 1f;
            if (isArenaMarchContext)
            {
                isCameraChanged = marchContext.CameraHeight != mainCameraTransform.position.y;
                lodLevel = 1;
            }
            else
            {
                isCameraChanged = worldEntry != null &&
                                  (marchContext.LodLevel != worldEntry.GetLODLevel() ||
                                   Math.Abs(marchContext.LodPercent - worldEntry.GetLODPercent()) > 0.0001f);
                if (isCameraChanged)
                {
                    lodLevel = worldEntry.GetLODLevel();
                    lodPercent = worldEntry.GetLODPercent();
                }
                
            }
            if (isCameraChanged) //lod和沙盘的数据不一样
            {
                isUpdateCameraPos = true;
                var cameraPosition = mainCameraTransform.position;
                marchContext.CameraPosition = cameraPosition;
                marchContext.CameraPositionChanged = true;
                marchContext.LodLevel = lodLevel;
                marchContext.LodPercent = lodPercent;
                marchContext.CameraHeight = mainCameraTransform.position.y;
                
                var marchLodLevel = marchContext.MarchLodLevel;
                //根据规则，转换lod数据
                marchContext.MarchLodLevel =
                    MarchHelper.GetMarchLodLevel(marchContext.LodLevel, marchContext.LodPercent);
                marchContext.needUpdateLod = marchLodLevel != marchContext.MarchLodLevel;
                
                marchContext.Lod0Scale = MarchHelper.GetLod0Scale(marchContext.LodLevel, marchContext.LodPercent);
                //marchContext.Lod1Scale = MarchHelper.GetLod1Scale(marchContext.LodLevel, marchContext.LodPercent);
                marchContext.Lod1Scale =
                    MarchHelper.GetLod1ScaleByHeight(marchContext.LodLevel, marchContext.CameraHeight);

                marchContext.showMarchSquare = marchContext.MarchLodLevel < WorldEntry.MaxShowMarchLodLevel;
                SquareDataManager.Instance.OnLodChanged(marchContext.LodLevel);
                if (DrawLineTool.p_IsInitialize)
                {
                    var drawLineTool = DrawLineTool.GetInstance();
                    drawLineTool.OnLodChanged(marchContext.LodLevel);
                }
            }

            return isUpdateCameraPos;
        }

        private bool isArenaMarchContext = false;

        public void SetArenaMarchContext(Transform cameraTransform)
        {
            marchContext.CameraHeight = cameraTransform.position.y;
            marchContext.LodLevel = 1;
            marchContext.LodPercent = 0.00425f;
            marchContext.MarchLodLevel = 1;
            marchContext.showMarchSquare = true;
            marchContext.Lod0Scale = 0.004f;
            mainCameraTransform = cameraTransform;
            isArenaMarchContext = true;
        }

        public void UnsetArenaMarchContext()
        {
            isArenaMarchContext = false;
            var worldCameraManager = WorldCameraManager.GetInstance();
            if (worldCameraManager)
            {
                var camera = worldCameraManager.GetCamera();
                if (camera)
                {
                    mainCameraTransform = WorldCameraManager.GetInstance().GetCamera().transform;
                }
            }
        }

        public float deltaTime;
        public float clientTime;
        private float lastCheckSimpleModelTime = 0;
        private float checkSimpleModelTime = 15;

        private int _fpsCount;
        private float _fpsDeltaTime= 0f;
        private short m_fpsSamplesCapacity = 1024;
        private short[] m_fpsSamples = new short[1024];
        private short m_indexSample = 0;
        private short CurrentFPS;
        private short AverageFPS;
        private short m_fpsSamplesCount = 0;
        
        public Action cachedTestAction;
        
        [BlackList]
        public void Update()
        {
#if UNITY_EDITOR
            if (cachedTestAction != null)
            {
                cachedTestAction();
                cachedTestAction = null;
            }
#endif
            RtsArenaManager.Instance.Update();
            OnUpdate();
        }
        [BlackList]
        public void OnUpdate(long handlerServerTime = 0,long handlerClientTime = 0)
        {
            UpdateChaseList();
            var unscaledDeltaTime = Time.unscaledDeltaTime;
            CurrentFPS = (short)(Mathf.RoundToInt(1f / unscaledDeltaTime));
            uint averageAddedFps = 0;

            m_indexSample++;
            if (m_indexSample >= m_fpsSamplesCapacity) m_indexSample = 0;
            m_fpsSamples[m_indexSample] = CurrentFPS;

            if (m_fpsSamplesCount < m_fpsSamplesCapacity)
            {
                m_fpsSamplesCount++;
            }

            for (int i = 0; i < m_fpsSamplesCount; i++)
            {
                averageAddedFps += (uint)m_fpsSamples[i];
            }
            AverageFPS = (short)((float)averageAddedFps / (float)m_fpsSamplesCount);


            long serverTime = TimeUtils.GetServerTimeMs();
            clientTime = TimeUtils.GetClientTickTime();

            if (handlerServerTime!=0)
            {
                serverTime = handlerServerTime;
                clientTime = handlerClientTime;
            }
            deltaTime = 0;
            if (_lastClientTime > 0)
            {
                deltaTime = clientTime - _lastClientTime;  //TODO: 这个有点问题吧？,
                if (deltaTime > 1)
                {
                    deltaTime = 0;
                }
            }
            else
            {
                deltaTime = Time.deltaTime;
            }
            lastCheckSimpleModelTime += Time.deltaTime;
            if (lastCheckSimpleModelTime > checkSimpleModelTime)
            {
                lastCheckSimpleModelTime = 0;
                CheckSimpleModeOpen();
            }

            _lastClientTime = clientTime;
            //更新MarchLOD
            k_UpdateLod.Begin();
            bool isUpdateCameraPos = UpdateMarchContext();
            if (isUpdateCameraPos)
            {
                FlyTextManager.Instance.OnUpdate(marchContext.Lod0Scale);
                _roundFightPlayer.UpdateLodLevel(marchContext);
            }

            UpdateDeleteDeadEffect();
            k_UpdateLod.End();
#if UNITY_EDITOR
            if (drawLodInfo)
                DrawLodInfo(marchContext);
#endif


            // 显示出来的模型数 
            int activeModelCount = 0;
            // 因为性能预算被丢弃的模型数
            int discardModelCount = 0;
            for (var i = 0; i < count; i++)
            {
                bool changeMarchInfo = false;
                var troopPath = paths[i];
                ref var segment = ref segments[i];
                var marchEntity = marchEnitiesBase[i];
                var marchInfo = marchEntity.MarchInfo;
                k_marchLine.Begin();
                var isMoving = troopPath.isMoving;
                // 是否要进入到下一个路段
                if (troopPath.UpdateNextSegment(serverTime))
                {
                    troopPath.UpdateSegment(ref segment);
                    if (segment.duration > 0)
                    {
                        marchInfo.SetForward(segment.direction);
                    }


                    if (marchEntity.LineId > 0)
                    {
                        RTSLuaCallCSharpManager.DelMarchLine(marchEntity.LineId);
                        marchEntity.LineId = 0;
                    }

                    bool isWonderNpc = false;
                    bool isBKArmyNpc = false;
                    if (marchEntity.isMonster)
                    {
                        isBKArmyNpc = marchEntity.RtsServerInfo.npcType == RtsNpcType.NPC_BKI_ARMY;
                        isWonderNpc = BattleUtils.IsWonderNpcBig(marchEntity.RtsServerInfo.npcType);
                    }

                    if (isShowTroopLine(marchEntity))
                    {
                        marchEntity.LineId =
                            RTSLuaCallCSharpManager.DrawMarchLine(troopPath.Points, troopPath.SegmentIndex, marchInfo.Team, marchEntity.RtsServerInfo.isAssemblyLeader, isWonderNpc, isBKArmyNpc);
                        changeMarchInfo = true;
                    }
                }
                // 计算当前路段
                // if (segment.duration > 0)
                // {
                //     segment.Calculate(deltaTime);
                // }
                segment.Calculate(clientTime);

                //if (marchData.Team == MarchHelper.TeamSelf)
                //    Debug.LogErrorFormat("[{3}:{4}]Segment.Calculate: serverDelta: {0} clientDelta: {1}, position: {2}",
                //        serverDeltaTime, clientDeltaTime, segment.clientPosition, Time.frameCount, serverTime);
                k_marchLine.End();
                k_marchState.Begin();
                bool isWalkToPark = false;
                // 行军状态下， 走到终点，状态改为驻扎
                bool isInMovingStatue = marchInfo.ClientMarchStatue == EMarchStatus.WALK ||
                                        marchInfo.ClientMarchStatue == EMarchStatus.Escape;
                if (isInMovingStatue && !troopPath.isMoving)
                {
                    //marchEntity.SetType((int) EMarchType.Park);
                    if (marchEntity.LineId > 0)
                    {
                        // 删除行军线
                        RTSLuaCallCSharpManager.DelMarchLine(marchEntity.LineId);
                        marchEntity.LineId = 0;
                    }
                    //如果不是自己的部队且在视野外停下来了，则需要删除
                    if (marchEntity.Team != (int)MarchTeam.Self && !marchEntity.isArenaMarch)
                    {
                        //野怪特殊处理
                        var isVisible = false;
                        var cameraManager = WorldCameraManager.GetInstance();
                        if (cameraManager)
                        {
                            isVisible = cameraManager.CheckPosInServerRect(marchEntity.Position);
                        }

                        if (!isVisible)
                        {
                            if (!marchEntity.isMonster)
                            {
                                isVisible = ResidentHandler.Inst.GetFunction("G_MarchManager.CheckSandBoxObjectVisible")
                                    .Func<long, int, bool>(marchEntity.Tid, (int)marchEntity.TargetCoordinateType);
                            }
                        }
                        if (!isVisible)
                        {
                            marchEntity.ReadyToHide();
                        }
                    }

                    isWalkToPark = true;
                    //是否是马上要进建筑或集结
                    var marchType = marchInfo.MarchType;
                    var isReinforceMonster = marchEntity.isMonster && marchEntity.RtsServerInfo.npcType == RtsNpcType.NPC_MIRACLE_REINFORCE;
                    var isMarchDieToHome = !marchEntity.isMonster && marchType == MarchType.DIE_5;
                    if (marchEntity.isArenaMarch && isMarchDieToHome)
                    {
                        marchEntity.ReadyToHide();
                    }
                    else if (marchType == MarchType.RETURN_4 || marchType == MarchType.AID_8 || marchType == MarchType.ASSEMBLY_JOIN_11 || marchType == MarchType.HOME_0 || isReinforceMonster || isMarchDieToHome)
                    {
                        marchEntity.FakeMoveForward(marchEntity.Position, marchInfo.GetTargetPosition());
                        if (marchType == MarchType.RETURN_4 || marchType == MarchType.HOME_0 || isReinforceMonster ||
                            (isMarchDieToHome && marchEntity.Team != 0))
                        {
                            marchEntity.ReadyToHide();
                        }
                    }

                    marchEntity.MarchInfo.IsWalkToPark = isWalkToPark;

                    // 如果卡车短行军假表现到了终点，则直接删除军队信息
                    if (marchEntity.bIsCargoTruckFakeMarch)
                    {
                        bool deleteSuccess = ResidentHandler.Inst.GetFunction("G_MarchManager.removeCargoTruckFakeMarch").Func<long, int, bool>(marchEntity.Tid, (int)marchEntity.TargetCoordinateType);
                        if (!deleteSuccess)
                        {
                            DestroyMarch(marchEntity.Tid, (int)marchEntity.RtsServerInfo.Type);
                        }
                    }
                } // 切换至战斗

                if (marchInfo.ClientMarchStatue == EMarchStatus.CrossingGate)
                {
                    marchInfo.UpdateCrossingGate();
                    if (marchInfo.ClientMarchStatue == EMarchStatus.WALK)//说明结束了
                    {
                        //模拟之后的路点
                        var serverInfo = marchEntity.RtsServerInfo;
                        serverInfo.lastFrameTime = TimeUtils.GetServerTimeMs();
                        var currentCoordinate = serverInfo.crossDetail.end;
                        var path = serverInfo.pathList;
                        //找到桥的起点，把这之前的都删了
                        var idx = 0;
                        if (path != null)
                        {
                            for (int j = 0; j < path.Length; j++)
                            {
                                if (BattleUtils.Distance(path[j], serverInfo.crossDetail.start) < 0.05f)
                                {
                                    idx = j;
                                    break;
                                }
                            }
                            var newPath = new Coordinate[path.Length - idx];
                            newPath[0] = currentCoordinate;
                            for (int j = 1; j < newPath.Length; j++)
                            {
                                newPath[j] = path[j + idx];
                            }
                            serverInfo.pathList = newPath;
                        }

                        serverInfo.coordinate = currentCoordinate;
                        troopPath.UpdateInfo(serverInfo, ref segment, true);
                        marchInfo.IsForceMoveChild = true;
                        marchInfo.SetForward(segment.direction);
                        marchEntity.SetMarchDefaultForward(segment.direction);
                        marchEntity.ChangeSquareStateByMarchType();
                        marchEntity.SetMarchDataToSquareData();
                    }
                }

                if (troopPath.isMoving)
                {
                    marchEntity.MarchInfo.IsWalkToPark = false;
                }
                var lastClientMarchStatue = marchInfo.ClientMarchStatue;
                if (lastClientMarchStatue != EMarchStatus.Battle && isMoving && !troopPath.isMoving)
                {
                    //停下来了，判断是否需要提前开战
                    if (marchInfo.TargetId != 0 && marchInfo.MarchType == MarchType.ATTACK_1)
                    {
                        var isPreBattle = marchEntity.isArenaMarch;

                        bool inBattle = true;
                        if (marchInfo.TargetType == TargetCoordinateType.BEACON_CASTLE_50 || marchInfo.TargetType == TargetCoordinateType.PRISON_CASTLE_49)
                        {
                            inBattle = marchInfo.ServerInbattle;
                        }
                        
                        if (inBattle)
                        {
                            marchEntity.SetMarchStatus(EMarchStatus.Battle);
                        }
                        changeMarchInfo = true;
                    }
                }
                //if (marchInfo.ClientMarchStatue != EMarchStatus.Battle && !troopPath.isMoving && marchEntity.GetBattleTarget() != null)
                //{
                //    marchEntity.SetMarchStatus(EMarchStatus.Battle);
                //    changeMarchInfo = true;
                //}
                if (marchInfo.ClientMarchStatue == EMarchStatus.Besiege && !troopPath.isMoving)
                {
                    if (marchEntity.LineId > 0)
                    {
                        // 删除行军线
                        RTSLuaCallCSharpManager.DelMarchLine(marchEntity.LineId);
                        marchEntity.LineId = 0;
                    }
                    //Debug.LogError("停下来了");
                    marchInfo.ClientMarchStatue = EMarchStatus.Battle;
                }

                k_marchState.End();


                k_SquareChildHideCount.Begin();
                if (marchContext.showMarchSquare)
                {
                    // 变化方阵
                    var battleSquare = marchEntity.GetBattleSquare();
                    if (battleSquare != null)
                    {
                        activeModelCount += battleSquare.GetActiveModelCount();
                        discardModelCount += battleSquare.GetDiscardModelCount();
                    }

                    if (changeMarchInfo)
                    {
                        marchEntity.SetMarchDataToSquareData();
                        var rtsServer = marchEntity.RtsServerInfo;
                        PlayerBattleSound(marchInfo.ClientMarchStatue, lastClientMarchStatue, rtsServer.targetType, oldTargetType, marchEntity.GetAudioEmiterObject(), marchEntity.Tid, rtsServer.team, rtsServer.targetTeam, marchEntity);
                    }

                }

                k_SquareChildHideCount.End();

                k_entiryUpdate.Begin();
                // 更新方阵、HUD动画等
                marchEntity.Update(marchContext, clientTime);
                k_entiryUpdate.End();
                // 不用模型了，序列帧就走Unity的裁剪，先注释掉
                //if (marchContext.CameraPositionChanged)
                //{
                //battleSquare?.Cull();
                // }
                // 设置位置
                k_changePos.Begin();
                if (marchEntity.Transform.position != marchInfo.Position)
                {
                    marchEntity.Transform.position = marchInfo.Position;
                    if (marchEntity.Hud != null)
                    {
                        marchEntity.Hud.UpdateFollowPos();
                        marchEntity.Hud.MarchHudLod0?.SetNickNamePosition();
                        marchEntity.Hud.MarchHudLod0?.SetRenownNamePosition();
                    }
                }

                k_changePos.End();

                k_changeHud.Begin();
                // 变化HUD
                var marchHud = marchEntity.Hud;
                if (marchHud != null)
                {
                    if (isUpdateCameraPos)
                    {
                        marchHud.OnCameraPosUpdated(marchContext);
                        marchHud.OnLodScaleChanged(marchContext);
                    }
                    marchHud.OnUpdate(marchContext);
                }
                k_changeHud.End();
            }

            k_SquareDataManager.Begin();
            SquareDataManager.Instance.Update(clientTime, deltaTime);
            bool spriteNeedUpdate = SquareDataManager.Instance.SpriteNeedUpdate();
            if (spriteUpdateEnabled != spriteNeedUpdate)
            {
                spriteUpdateEnabled = spriteNeedUpdate;
                ArmyManager.SpriteParticleSystemManager.SetCreatorEnabled(spriteUpdateEnabled);
                if (spriteUpdateEnabled)
                {
                    SquareDataManager.Instance.ForceUpdateFightingTroopStatus();
                }
            }
            k_SquareDataManager.End();

            k_handlermarchshadow.Begin();
            // 根据模型数量控制阴影是否显示 (注掉，现在沙盘不用GPU Skinning了）
            //GPUInstancingManager.IsShadowActive = activeModelCount < RTSLuaCallCSharpManager.MaxModelWithShadow;

            var maxModel = RTSLuaCallCSharpManager.MaxModelWithoutShadow;
            if (activeModelCount > maxModel)
            {
                // 每个部队减少多少个小兵
                int modelPerTroop = (activeModelCount - maxModel + count - 1) / count;
                // 高于减小兵平均线的部队不再减少
                int discardPerTroop = (discardModelCount + count - 1) / count;
                for (var i = 0; i < count; i++)
                {
                    var marchEntity = marchEnitiesBase[i];
                    var battleSquare = marchEntity.GetBattleSquare();
                    if (battleSquare == null)
                        continue;

                    if (battleSquare.GetDiscardModelCount() <= discardPerTroop)
                    {
                        int discardCount = battleSquare.Discard(modelPerTroop);
                        activeModelCount -= discardCount;
                        if (activeModelCount <= maxModel)
                            break;
                    }
                }
            }
            else if (discardModelCount > 0 &&
                     // 要么能各个部队平均恢复1个小兵，要么全部恢复后也在最大值之下
                     // 避免一帧恢复一帧丢弃，来回横跳
                     (activeModelCount + Count <= maxModel || activeModelCount + discardModelCount <= maxModel))
            {
                // 低于减小兵平均线的部队不再复原
                int discardPerTroop = (discardModelCount + count - 1) / count;
                for (var i = 0; i < count; i++)
                {
                    var marchEntity = marchEnitiesBase[i];
                    var battleSquare = marchEntity.GetBattleSquare();
                    if (battleSquare == null)
                        continue;

                    if (battleSquare.GetDiscardModelCount() >= discardPerTroop)
                    {
                        int recoverCount = battleSquare.Recover(1);
                        activeModelCount += recoverCount;
                        if (activeModelCount > maxModel)
                            break;
                    }
                }
            }

            if (waitDeleteCount > 0)
            {
                for (int j = waitDeleteCount - 1; j >= 0; j--)
                {
                    if (!_waitDeleteEntityList[j].IsWaitDelete)
                    {
                        _waitDeleteEntityList[j].UpdateOnWaitDispose();
                    }
                    else
                    {
                        var id = _waitDeleteEntityList[j].Tid;
                        var type = _waitDeleteEntityList[j].TargetCoordinateType;
                        MarchBesiegeManager.Instance.RemoveAttackTarget(id, type);
                        MarchBesiegeManager.Instance.RemoveReachTime(id, type);
                        _waitDeleteEntityList[j].Dispose();
                        DeleteWaitEntity(_waitDeleteEntityList[j], j);
                    }

                }
            }

            marchContext.CameraPositionChanged = false;
            k_handlermarchshadow.End();

            k_updateForce.Begin();
            UpdateFocus();
            k_updateForce.End();

            k_RoundFightHelper.Begin();
            _roundFightPlayer.Update(clientTime);
            k_RoundFightHelper.End();

            if (hasDelayDestroyMarch)
            {
                for (int i = 0; i < delayDestroyMarchList.Count; i++)
                {
                    var marchEntity = delayDestroyMarchList[i];
                    var troopKey = marchEntity.Tid;
                    var type = (int)marchEntity.RtsServerInfo.Type;
                    if (marchEntity.isClientCreateMarch())
                    {
                        DestroyMarch(marchEntity.Tid, (int)marchEntity.RtsServerInfo.Type);
                    }
                    else
                    {
                        var deleteSuccess = ResidentHandler.Inst.GetFunction("G_MarchManager.DestroyArmyFromExternal").Func<long, int, bool>(troopKey, type);
                        if (!deleteSuccess)
                        {
                            DestroyMarch(marchEntity.Tid, (int)marchEntity.RtsServerInfo.Type);
                            Debug.LogError(troopKey + "lua删除失败");
                        }
                    }
                    
                }
                delayDestroyMarchList.Clear();
                hasDelayDestroyMarch = false;
            }
        }



        private void UpdateChaseList()
        {
            if (updateChaseList.Count > 0)
            {
                foreach (var entity in updateChaseList)
                {
                    var serverInfo = entity.RtsServerInfo;
                    var attackTargetId = serverInfo.attackTargetId;
                    var targetMarch = GetMarchEntityByIdAndType(attackTargetId,serverInfo.attackTargetType);
                    if (targetMarch != null && targetMarch.MarchInfo.SoldierCount > 0 && targetMarch.RtsServerInfo.pathList != null && targetMarch.RtsServerInfo.pathList.Length > 0)
                    {
                        {
                            entity.CheckNeedGenerateChasePathList(targetMarch, serverInfo);
                            if (rtsEntityDictionary.TryGetValue(entity.TargetCoordinateType,out var dictionary))
                            {
                                if (dictionary.TryGetValue(entity.Tid,out var index) && index < paths.Count)
                                {
                                    var troopPath = paths[index];
                                    ref var segment = ref segments[index];
                                    // Step01: 更新部队位置&朝向； 否则后面位置数据不对
                                    troopPath.UpdateInfo(entity.RtsServerInfo, ref segment);
                                    entity.MarchInfo.IsForceMoveChild = troopPath.IsForceMoveChild;
                                    entity.SetMarchDataToSquareData();
                                
                                    var clientMarchStatus = GetClientMarchType(entity.RtsServerInfo);
                                
                                    if (entity.MarchInfo.ClientMarchStatue != clientMarchStatus)
                                    {
                                        entity.SetMarchStatus(clientMarchStatus);
                                    }
                                
                                    if (troopPath.NeedUpdateLine) 
                                    {
                                        troopPath.NeedUpdateLine = false;
                                        if (entity.LineId > 0)  //删除之前的
                                        {
                                            RTSLuaCallCSharpManager.DelMarchLine(entity.LineId);
                                            entity.LineId = 0;
                                        }
                                        if(troopPath.Points!=null && troopPath.Points.Count>0) //如果需要绘制新的，则绘制
                                        {
                                            bool isWonderNpc = false;
                                            if (entity.isMonster)
                                            {
                                                isWonderNpc = BattleUtils.IsWonderNpcBig(entity.RtsServerInfo.npcType);
                                            }
                                            entity.LineId = RTSLuaCallCSharpManager.DrawMarchLine(troopPath.Points, troopPath.SegmentIndex, entity.MarchInfo.Team,entity.RtsServerInfo.isAssemblyLeader,isWonderNpc);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            
                updateChaseList.Clear();
            }
            if (updateChaseAttackerList.Count > 0)
            {
                for (int i = updateChaseAttackerList.Count - 1; i >= 0 ; i--)
                {
                    var marchEntity = updateChaseAttackerList[i];
                    var attackers = MarchBesiegeManager.Instance.GetAttackerIdByTargetId(marchEntity.Tid,marchEntity.TargetCoordinateType);
                    deleteAttackTargetList.Clear();
                    if (attackers != null)
                    {
                        foreach (var attacker in attackers)
                        {
                            //判断是否需要模拟追击路线
                            var attackerMarch = GetMarchEntityByIdAndType(attacker.Uid,attacker.Type);
                            if (attackerMarch != null)
                            {
                                var serverInfo = attackerMarch.RtsServerInfo;
                                if (serverInfo.marchType == MarchType.ATTACK_1 &&
                                    serverInfo.attackTargetId == marchEntity.Tid && serverInfo.targetId == marchEntity.Tid)
                                {
                                    attackerMarch.CheckNeedGenerateChasePathListAndRefresh(marchEntity);
                                }
                                else
                                {
                                    //Debug.LogError("攻击缓存数据有误,攻击方"+attackerMarch.Tid + " " + "目标"+marchEntity.Tid); 没必要报错 部队A追击部队B 追不上 B进驻建筑 就会有serverInfo.attackTargetId ~= marchEntity.Tid
                                    deleteAttackTargetList.Add(attacker);
                                }
                            }
                        }
                    }
               
                    for (int j = 0; i < deleteAttackTargetList.Count; i++)
                    {
                        var id = deleteAttackTargetList[j].Uid;
                        var type = deleteAttackTargetList[j].Type;
                        MarchBesiegeManager.Instance.RemoveAttackTarget(id,type);
                        MarchBesiegeManager.Instance.RemoveReachTime(id,type);
                    }
                }
                
                updateChaseAttackerList.Clear();
            }
        }


        [BlackList]
        public float GetLodPercent()
        {
            return marchContext.LodPercent;
        }
        [BlackList]

        public void RemoveMarchSquare(MarchEntity marchEntity)
        {
            MarchBesiegeManager.Instance.RemoveAttacker(marchEntity.Tid,marchEntity.TargetCoordinateType);
            MarchBesiegeManager.Instance.RemoveAttackTarget(marchEntity.Tid,marchEntity.TargetCoordinateType);
            MarchBesiegeManager.Instance.RemoveReachTime(marchEntity.Tid,marchEntity.TargetCoordinateType);
            _waitDeleteEntityList.Add(marchEntity);
            waitDeleteCount++;
        }
        [BlackList]
        private void DeleteWaitEntity(MarchEntity waitDeleteEntity,int index)
        {
            _waitDeleteEntityList.RemoveAt(index);
            waitDeleteCount--;
            RecoverMarchEntity(waitDeleteEntity);
        }
        [BlackList]
        public int GetPlayerAttackerCount(long uid,TargetCoordinateType type)
        {
            return playerBattle.GetPlayerAttackerCount(uid,type);
        }

        [BlackList]
        public void Dispose()
        {
            rtsEntityDictionary.Clear();
            paths.Clear();

            foreach (var marchEntity in marchEnitiesBase)
            {
                marchEntity.Dispose();
                RecoverMarchEntity(marchEntity);
            }
            marchEnitiesBase.Clear();

            foreach (var marchEntity in _waitDeleteEntityList)
            {
                marchEntity.Dispose();
                RecoverMarchEntity(marchEntity);
            }
            _waitDeleteEntityList.Clear();

            marchContext = null;
            mainCameraTransform = null;
            _rtsResMgr = null;
            _hudConfig.Dispose();
            for (int i = 0; i < marchEntityPool.Count; i++)
            {
                marchEntityPool[i].DisposeHud();
            }
            marchEntityPool.Clear();
            for (int i = 0; i < monsterEntityPool.Count; i++)
            {
                monsterEntityPool[i].DisposeHud();
            }
            DeleteAllDeadEffect();
            monsterEntityPool.Clear();
            marchEntityRoot = null;
            monsterEntityRoot = null;
            SelectedObjRoot = null;
            MarchBesiegeManager.Instance.Dispose();
            _roundFightPlayer.Dispose();
            _roundFightPlayer = null;
            tempPlayerMarches.Clear();

            ClassManager.GetInstance().Clear<TroopPath>();
            GTAGameStart.eventManager.RemoveEvent<com.youzu.warh.protocol.SCRoundFight>(ClientEvent.RoundFight,OnRoundFight);
            UpdateSoldierCallBack = null;
            Instance = null;
        }

        private List<MarchEntity> tempPlayerMarches = new List<MarchEntity>(32);
        
        [BlackList]
        public List<MarchEntity> GetPlayerMarches(long marchID, out long playerID)
        {
            playerID = GetMarchPlayerID(marchID);
            if (playerID == 0)
                return null;

            PlayerBattleList list;
            if (!playerToMarch.TryGetValue(playerID, out list))
                return null;
            //var ret = new List<MarchEntity>(list.Count);
            tempPlayerMarches.Clear();
            foreach (var troop in list.marchList)
                tempPlayerMarches.Add(GetMarchEntityByIdAndType(troop.Uid,troop.Type));

            return tempPlayerMarches;
        }
        [BlackList]
        public long GetMarchPlayerID(long marchID)
        {
            long playerID;
            if (!marchToPlayer.TryGetValue(marchID, out playerID))
                return 0;

            return playerID;
        }

        [BlackList]
        public void OnAttackRemoved(long attacker,TargetCoordinateType type)
        {
            playerBattle.OnAttackRemoved(attacker,type);
        }
        [BlackList]
        public void SetFocusTroopId(long trooopId,int type)
        {
            // 跟随对象取消请求一下视野
            if (trooopId == 0 && _FocusTroopId != 0)
            {
                if (eventLua == null)
                {
                    eventLua = LuaManager.mainState.GetFunction("L_SandBoxManager.onRequsetView");
                }
                if (eventLua != null)
                {
                    eventLua.Call(true);
                }
            }

            _FocusTroopId = trooopId;
            _FocusTroopType = (TargetCoordinateType)type;
        }
        
        [BlackList]
        public void SetFocusTroopSpeed(float speed,float startX,float startZ)
        {
            _FocusLerpTime = speed;
            _FocusLerpStartTime = Time.time;
            _FocusStartPosition = new Vector2(startX, startZ);
        }
        [BlackList]
        public void SetChasingTroopState(string tid, bool isChasing)
        {
            // if (itemKeyAndIndexMap.TryGetValue(tid, out int troopIndex))
            // {
            //     var chasingData = marchEnitiesBase[troopIndex];
            //     if (chasingData.Hud != null)
            //     {
            //         chasingData.MarchInfo.BeChasingByMonster = isChasing;
            //     }
            // }
        }
        /// <summary>
        /// 把玩家ID与行军id绑定起来
        /// </summary>
        /// <param name="marchID"></param>
        /// <param name="playerID"></param>
        private void AddPlayer2March(long marchID,TargetCoordinateType type, long playerID)
        {
            PlayerBattleList list;
            if (!playerToMarch.TryGetValue(playerID, out list))
            {
                list = RTSClassPoolManager.GetPlayerBattleListPool();
                playerToMarch.Add(playerID, list);
            }

            list.marchList.Add(new Troop(marchID, type));
            marchToPlayer.Add(marchID, playerID);
        }

        private void RemovePlayer2March(long marchID,TargetCoordinateType type)
        {
            long playerID;
            if (!marchToPlayer.TryGetValue(marchID, out playerID))
                return;

            PlayerBattleList listObj;
            if (!playerToMarch.TryGetValue(playerID, out listObj))
                return;
            var list = listObj.marchList;
            var troop = new Troop(marchID, type);
            // 数量应该不多，先用遍历用着
            for (var i = 0; i < list.Count; i++)
            {
                if (troop.Equals(list[i]))
                {
                    var tail = list.Count - 1;
                    var t = list[tail];
                    list[tail] = troop;
                    list[i] = t;
                    list.RemoveAt(tail);
                    if (list.Count == 0)
                        playerToMarch.Remove(playerID);

                    break;
                }
            }
            RTSClassPoolManager.RecoverPlayerBattleList(listObj);
            marchToPlayer.Remove(marchID);
        }

        private void UpdateFocus()
        {
            if (_FocusTroopId!=0)
            {
                // 获取部队索引
                if (!rtsEntityDictionary.TryGetValue(_FocusTroopType,out var dictionary))
                {
                    return;
                }
                
                
                if (!dictionary.TryGetValue(_FocusTroopId, out int itemIndex))
                {
                    _FocusTroopId = 0;//跟随部队的索引如果找不到说明部队已经销毁，_FocusTroopId置空
                    return;
                }

                // 获取部队信息
                var marchEntity = marchEnitiesBase[itemIndex];
                if (marchEntity != null && marchEntity.IsMoving())
                {
                    var position = marchEntity.MarchInfo.Position;
                    var cameraPosition = new Vector2(position.x, position.z);
                    if (_FocusLerpStartTime > 0)
                    {
                        var percent = (Time.time - _FocusLerpStartTime) / _FocusLerpTime;
                        if (percent >= 1)
                        {
                            percent = 1;
                            _FocusLerpStartTime = 0;
                        }

                        cameraPosition = Vector2.Lerp(_FocusStartPosition, cameraPosition, percent);
                    }
                    WorldCameraManager.ChangPosToViewCenter(cameraPosition);
                    FocusTroopAction?.Action(cameraPosition.x,cameraPosition.y);
                }
                else
                {
                    _FocusTroopId = 0;
                }
            }
        }

        #region 调试功能

#if UNITY_EDITOR
        private YText debugText;
        


        private YText GetDebugText()
        {
            if (debugText)
                return debugText;

            var go = GameObject.Find("Y_DebugText");
            if (go == null)
                return null;

            debugText = go.GetComponent<YText>();
            debugText.horizontalOverflow = HorizontalWrapMode.Overflow;
            debugText.verticalOverflow = VerticalWrapMode.Overflow;
            return debugText;
        }

        private void DrawLodInfo(MarchContext marchContext)
        {
            var text = GetDebugText();
            if (text == null) return;

            text.text = $"\nLOD: {marchContext.LodLevel} ({marchContext.LodPercent:0.00}%)" +
                        $"\nMarch LOD: {marchContext.MarchLodLevel}, scale: {marchContext.Lod0Scale:0.0000}" +
                        $"\n AVG FPS:{AverageFPS}"
                        ;
        }
#endif

        #endregion

        private List<Troop> _selectingUIList = new List<Troop>(16);
        public void SelectBattleTroop(long targetId,TargetCoordinateType type,float otherAlpha, int team = -1, Troop troop = default)
        {
            List<Troop> list = playerBattle.GetAllRelationTroop(new Troop(targetId, type)); //获得所有有关系的部队
            if (!Equals(troop, default(Troop)))
            {
                list.Add(troop);
            }
            for (int i = 0; i < marchEnitiesBase.Count; i++)//
            {
                var needHide = !list.Contains(new Troop(marchEnitiesBase[i].Tid,marchEnitiesBase[i].TargetCoordinateType));
                if (needHide)//改变无关系的部队hud alpha值
                {
                    var entity = marchEnitiesBase[i];
                    entity.Hud?.TurnAlphaTo(otherAlpha);
                }
            }
            SetOtherCanvas(otherAlpha);
            bool isOn = otherAlpha == BattleUtils.TransparentAlpha;

            if (!isOn)
            {
                if (_selectingUIList.Count > 0)
                {
                    foreach (var selectingUI in _selectingUIList)
                    {
                        var entity = GetMarchEntityByIdAndType(selectingUI.Uid, selectingUI.Type);
                        if (entity != null)
                        {
                            if (entity.MarchInfo.MarchType != MarchType.DEFENCE_6) //城防头像不包括
                            {
                                entity.Hud?.ForceShowSelectedUI(false, true);
                                entity.Hud?.TurnAlphaTo(BattleUtils.OpaqueAlpha);
                                MoveHudToOriginCanvas(entity.Mono.transform, entity.isMonster);
                            }
                        }
                    }

                    _selectingUIList.Clear();
                }
            }

            if (isOn)
            {
                _selectingUIList.AddRange(list);
            }
            for (int i = 0; i < list.Count; i++)
            {
                SetTroopHudAlpha(list[i], isOn);
            }
        }

        private void MoveTargetHudToSelectCanvas(Transform hud)
        {
            hud.transform.SetParent(SelectedObjRoot);
        }

        private void MoveHudToOriginCanvas(Transform hud,bool isMonster)
        {
            if (isMonster)
            {
                hud.transform.SetParent(monsterEntityRoot);
            }
            else
            {
                hud.transform.SetParent(marchEntityRoot);
            }

            IsAllHudToOriginCavas();
        }

        private void IsAllHudToOriginCavas()
        {
            if (SelectedObjRoot!= null && SelectedObjRoot.childCount == 0)
            {
                SetOtherCanvas(1);
            }
        }

        public void SelectBattleTroops(List<Troop> targetIdList,float otherAlpha)
        {
            if (targetIdList == null || targetIdList.Count == 0) return;
            List<Troop> list = null;
            for (int i = 0; i < targetIdList.Count; i++)
            {
                var target = targetIdList[i];
                var relationList = playerBattle.GetAllRelationTroop(target); //获得所有有关系的部队
                if (list == null)
                {
                    list = relationList;
                }
                else
                {
                    list.AddRange(relationList);
                }
                var entity = GetMarchEntityByIdAndType(target.Uid,target.Type);
                if (entity != null && entity.MarchInfo.IsInBattleState)
                {
                    var battleTargetId = entity.MarchInfo.BattleTargetId;
                    if (battleTargetId!=0)
                    {
                        list.Add(new Troop(battleTargetId,entity.TargetCoordinateType));
                    }
                }
            }

            for (int i = 0; i < marchEnitiesBase.Count; i++)//
            {
                var needHide = !list.Contains(new Troop(marchEnitiesBase[i].Tid, marchEnitiesBase[i].TargetCoordinateType));
                if (needHide)//改变无关系的部队hud alpha值
                {
                    var entity = marchEnitiesBase[i];
                    entity.Hud?.TurnAlphaTo(otherAlpha);
                }
            }
            SetOtherCanvas(otherAlpha);
            bool isOn;
            if (otherAlpha == BattleUtils.TransparentAlpha)
            {
                isOn = true;
            }
            else
            {
                isOn = false;
            }
            for (int i = 0; i < list.Count; i++)
            {
                SetTroopHudAlpha(list[i], isOn);
            }
        }
        /// <summary>
        /// 将所有选中的部队及相关战斗的部队放回原始的canvas
        /// </summary>
        /// <param name="targetIdList"></param>
        public void MoveSelectMarchToNormalCanvas(List<long> targetIdList)
        {
            List<Troop> list = null;
            for (int i = 0; i < targetIdList.Count; i++)
            {
                var id = targetIdList[i];
                var target = new Troop(id,TargetCoordinateType.MARCH_3);
                var relationList = playerBattle.GetAllRelationTroop(target);//获得所有有关系的部队
                if (list == null)
                {
                    list = relationList;
                }
                else
                {
                    list.AddRange(relationList);
                }
                var entity = GetMarchEntityByIdAndType(target.Uid,target.Type);
                if (entity != null && entity.MarchInfo.IsInBattleState)
                {
                    var battleTargetId = entity.MarchInfo.BattleTargetId;
                    if (battleTargetId != 0)
                    {
                        list.Add(new Troop(battleTargetId,entity.MarchInfo.attackTargetType));
                    }
                }
            }

            for (int i = 0; i < marchEnitiesBase.Count; i++)//
            {
                var needHide = !list.Contains(new Troop(marchEnitiesBase[i].Tid,marchEnitiesBase[i].TargetCoordinateType));
                if (needHide)
                {
                    var entity = marchEnitiesBase[i];
                    entity.Hud?.TurnAlphaTo(1);
                }
            }
            SetOtherCanvas(1);

            for (int i = 0; i < list.Count; i++)
            {
                var troop = list[i];
                if (rtsEntityDictionary.TryGetValue(troop.Type,out var dictionary))
                {
                    if (dictionary.TryGetValue(troop.Uid,out var index))
                    {
                        var entity = marchEnitiesBase[index];
                        if (entity.MarchInfo.MarchType != MarchType.DEFENCE_6) //城防头像不包括
                        {
                            entity.Hud?.TurnAlphaTo(1);
                            MoveHudToOriginCanvas(entity.Mono.transform, entity.isMonster);
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 将除了目标部队和自己的部队全都隐藏或显示
        /// </summary>
        /// <param name="targetId"></param>
        /// <param name="selfId"></param>
        /// <param name="alpha"></param>
        /// <param name="isDragNormalStyle"></param>
        /// <param name="team"></param>
        public void DragTroopToTargetShowHud(long targetId,int targetType, long selfId, int selfType,float otherAlpha, bool isDragNormalStyle, int team = -1)
        {
            for (int i = 0; i < marchEnitiesBase.Count; i++)
            {
                var needHide = targetId != marchEnitiesBase[i].Tid && selfId != marchEnitiesBase[i].Tid;
                if (needHide)
                {
                    var entity = marchEnitiesBase[i];
                    entity.Hud?.TurnAlphaTo(otherAlpha);
                }
            }
            SetOtherCanvas(otherAlpha);
            bool isOn;
            if (otherAlpha == 0.6f)
            {
                isOn = true;
            }
            else
            {
                isOn = false;
            }
            SetTroopHudAlpha(new Troop(targetId,(TargetCoordinateType)targetType), isOn, !isOn);
            if (selfId != 0)
            {
                SetTroopHudAlpha(new Troop(selfId,(TargetCoordinateType)selfType), isOn);
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="tid"></param>
        /// <param name="isOn"></param>
        /// <param name="battleStyle"></param>
        /// <param name="team"></param>
        [BlackList]
        public void SetTroopHudAlpha(Troop troop,bool isOn,bool isShowBattleStyle = true)
        {
            var entity = GetMarchEntityByIdAndType(troop.Uid, troop.Type);
            if (entity != null)
            {
                if (isOn) //选中
                {
                    entity.Hud?.ForceShowSelectedUI(true, isShowBattleStyle);
                    entity.Hud?.TurnAlphaTo(BattleUtils.OpaqueAlpha);
                    MoveTargetHudToSelectCanvas(entity.Mono.transform);
                }
                else
                {
                    entity.Hud?.ForceShowSelectedUI(false, isShowBattleStyle);
                    entity.Hud?.TurnAlphaTo(BattleUtils.OpaqueAlpha);
                    MoveHudToOriginCanvas(entity.Mono.transform, entity.isMonster);
                }
            }
        }

        public void SetTroopHudAlpha(long troopId, int type, bool isOn)
        {
            SetTroopHudAlpha(new Troop(troopId, (TargetCoordinateType)type), isOn);
        }

        private void SetOtherCanvas(float targetAlpha)
        {
            DOTween.To(() => {
                return _monsterCanvasGroup.alpha;
            },(float alpha) => {
                _monsterCanvasGroup.alpha = alpha;
            }, targetAlpha, tweenAlphaTime);

            DOTween.To(() => {
                return _marchCanvasGroup.alpha;
            }, (float alpha) => {
                _marchCanvasGroup.alpha = alpha;
            }, targetAlpha, tweenAlphaTime);
        }
        
        private bool showAllSquareCircle = false;
        private List<GameObject> squareCircle = new List<GameObject>();
        
        public void ShowAllSquareCircle()
        {
            showAllSquareCircle = !showAllSquareCircle;
            if (showAllSquareCircle)
            {
                for (int i = 0; i < marchEnitiesBase.Count; i++)
                {
                    var gameObject = GameObject.CreatePrimitive(PrimitiveType.Cylinder);
                    gameObject.transform.localScale = new Vector3(0.3f,UnityEngine.Random.Range(0.01f,0.1f),0.3f);
                    gameObject.GetComponent<Collider>().enabled = false;
                    gameObject.transform.SetParent(marchEnitiesBase[i].Transform);
                    gameObject.transform.localPosition = Vector3.zero;
                    gameObject.transform.localEulerAngles = Vector3.zero;
                    squareCircle.Add(gameObject);
                }
            }
            else
            {
                for (int i = 0; i < squareCircle.Count; i++)
                {
                    GameObject.Destroy(squareCircle[i]);
                }
                squareCircle.Clear();
            }
        }
        public bool IsSelfAttack(long id,TargetCoordinateType target)
        {
            return playerBattle.IsSelfAttack(id,target);
        }

        [BlackList]
        public void ForceSetSquareChildPosition()
        {
            for (int i = 0; i < marchEnitiesBase.Count; i++)
            {
                var entity = marchEnitiesBase[i];
                if (entity!=null)
                {
                    entity.ForceSetPosition();
                }
            }
        }

        public void ChangedArenaMarchPos(float x,float y,float z,int id)
        {

            if (rtsEntityDictionary.TryGetValue(TargetCoordinateType.MARCH_3, out var dictionary))
            {
                if (dictionary.TryGetValue(id, out var index))
                {
                    if (index < marchEnitiesBase.Count)
                    {
                        var pos = new Vector3(x, 0, z);
                        var entity = marchEnitiesBase[index];
                        if (entity != null)
                        {
                            entity.ForceSetPosition(pos);
                        }
                        var troopPath = paths[index];
                        troopPath.ClientPosition = pos;
                        troopPath.ServerPosition = pos;
                        ref var segment = ref segments[index];
                        segment.UpdateCurrentPosition(pos - (Vector3)entity.MarchInfo.PosOffset);
                    }
                }
            }
        }

        public void CreateEsCapeEffect(Vector3 position)
        {
            var deathEffect = RTSLuaCallCSharpManager.GetResourceById(1014);
            if (deathEffect != null)
            {
                deathEffect.SetActive(false);
                deathEffect.SetActive(true);
                deathEffect.transform.position = position;
                deathEffect.transform.eulerAngles = new Vector3(0, Random.Range(0, 360), 0);
            }
            deadEffectList.Add(new DeadEffect()
            {
                effect = deathEffect,
                startTime = Time.time
            }) ;
        }

        private void UpdateDeleteDeadEffect()
        {
            for (int i = deadEffectList.Count-1; i >= 0; i--)
            {
                var effectObj = deadEffectList[i];
                if (Time.time - effectObj.startTime > 10)
                {
                    RTSLuaCallCSharpManager.RecoverEffectById(1014, effectObj.effect);
                    deadEffectList.RemoveAt(i);
                }
            }
        }
        private void DeleteAllDeadEffect()
        {
            for (int i = deadEffectList.Count - 1; i >= 0; i--)
            {
                var effectObj = deadEffectList[i];
                RTSLuaCallCSharpManager.RecoverEffectById(1014, effectObj.effect);
                deadEffectList.RemoveAt(i);
            }
            deadEffectList.Clear();
        }

        [LuaCallCSharp]
        public void UpdateCargoTruckHudStateDescText(long troopId, TargetCoordinateType troopType, bool bIsActiveDescText, string content)
        {
            if (!rtsEntityDictionary.TryGetValue(troopType, out var dictionary))
            {
                return;
            }
            if (!dictionary.TryGetValue(troopId, out var itemIndex))
            {
                return;
            }
            var marchEntity = marchEnitiesBase[itemIndex];
            (marchEntity.Hud as CargoTruckHud)?.SetDescTextInfo(bIsActiveDescText, content);
            (marchEntity.Hud as CargoTruckHud)?.UpdateShow();
        }

        [LuaCallCSharp]
        public void UpdateSmugglerHudIcon(long troopId, TargetCoordinateType troopType, string icon)
        {
            //if (!rtsEntityDictionary.TryGetValue(troopType, out var dictionary))
            //{
            //    return;
            //}
            //if (!dictionary.TryGetValue(troopId, out var itemIndex))
            //{
            //    return;
            //}
            //var marchEntity = marchEnitiesBase[itemIndex];
            //(marchEntity.Hud as SmugglerHud)?.SetLod0Icon(icon);
        }

        [LuaCallCSharp]
        public void UpdateSmugglerWorldPosTip(Int64 troopId, TargetCoordinateType troopType, bool bShow, string tip)
        {
            if (!rtsEntityDictionary.TryGetValue(troopType, out var dictionary))
            {
                return;
            }
            if (!dictionary.TryGetValue(troopId, out var itemIndex))
            {
                return;
            }
            var marchEntity = marchEnitiesBase[itemIndex];
            (marchEntity.Hud as SmugglerHud)?.UpdateSmugglerWorldPosTip(troopId,  bShow, tip);
        }

        [LuaCallCSharp]
        public void UpdateCargoTruckHudTroopCount(long troopId, TargetCoordinateType troopType, int troopCount)
        {
            if (!rtsEntityDictionary.TryGetValue(troopType, out var dictionary))
            {
                return;
            }
            if (!dictionary.TryGetValue(troopId, out var itemIndex))
            {
                return;
            }
            var marchEntity = marchEnitiesBase[itemIndex];
            (marchEntity.Hud as CargoTruckHud)?.SetTroopCount(troopCount);
        }
        
        [LuaCallCSharp]
        public void SetAlliancePracticeBossNameText(long troopId, TargetCoordinateType troopType, string name)
        {
            if (!rtsEntityDictionary.TryGetValue(troopType, out var dictionary))
            {
                return;
            }
            if (!dictionary.TryGetValue(troopId, out var itemIndex))
            {
                return;
            }
            var marchEntity = marchEnitiesBase[itemIndex];
            (marchEntity.Hud as PractiseMarchHud)?.SetBossNameText(name);
        }
        
        [LuaCallCSharp]
        public void SetAlliancePracticeBossTimeText(long troopId, TargetCoordinateType troopType, string timeStr)
        {
            if (!rtsEntityDictionary.TryGetValue(troopType, out var dictionary))
            {
                return;
            }
            if (!dictionary.TryGetValue(troopId, out var itemIndex))
            {
                return;
            }
            var marchEntity = marchEnitiesBase[itemIndex];
            (marchEntity.Hud as PractiseMarchHud)?.SetTimeText(timeStr);
        }
        
        [LuaCallCSharp]
        public void SetAlliancePracticeBossCDStateRootActive(long troopId, TargetCoordinateType troopType, bool active)
        {
            if (!rtsEntityDictionary.TryGetValue(troopType, out var dictionary))
            {
                return;
            }
            if (!dictionary.TryGetValue(troopId, out var itemIndex))
            {
                return;
            }
            var marchEntity = marchEnitiesBase[itemIndex];
            (marchEntity.Hud as PractiseMarchHud)?.SetCDStateRootActive(active);
        }
        
        [LuaCallCSharp]
        public void SetAlliancePracticeBossMvpText(long troopId, TargetCoordinateType troopType, string mvpText)
        {
            if (!rtsEntityDictionary.TryGetValue(troopType, out var dictionary))
            {
                return;
            }
            if (!dictionary.TryGetValue(troopId, out var itemIndex))
            {
                return;
            }
            var marchEntity = marchEnitiesBase[itemIndex];
            (marchEntity.Hud as PractiseMarchHud)?.SetMvpText(mvpText);
        }
        
        [LuaCallCSharp]
        public void SetAlliancePracticeBossRewardStageText(long troopId, TargetCoordinateType troopType, string rewardStageText)
        {
            if (!rtsEntityDictionary.TryGetValue(troopType, out var dictionary))
            {
                return;
            }
            if (!dictionary.TryGetValue(troopId, out var itemIndex))
            {
                return;
            }
            var marchEntity = marchEnitiesBase[itemIndex];
            (marchEntity.Hud as PractiseMarchHud)?.SetRewardStageText(rewardStageText);
        }
        
        [LuaCallCSharp]
        public void SetAlliancePracticeBossRewardProgressBar(long troopId, TargetCoordinateType troopType, float ratio)
        {
            if (!rtsEntityDictionary.TryGetValue(troopType, out var dictionary))
            {
                return;
            }
            if (!dictionary.TryGetValue(troopId, out var itemIndex))
            {
                return;
            }
            var marchEntity = marchEnitiesBase[itemIndex];
            (marchEntity.Hud as PractiseMarchHud)?.SetRewardProgressBar(ratio);
        }
        [LuaCallCSharp]
        public void setUsererServerId(long id)
        {
            userServerId = id;
        }
        [LuaCallCSharp]
        public void SetSandBoxServerId(long id)
        {
            sandBoxServerId = id;
        }
        
        public long GetSandBoxServerId()
        {
            return sandBoxServerId;
        }

        private bool isShowTroopLine(MarchEntity entity)
        {
            bool isShow = true;
            if (entity.isClientCreateMarch() || 
                entity.TargetCoordinateType == TargetCoordinateType.INTERCITY_TRADE_TRUCK_45 || 
                entity.TargetCoordinateType == TargetCoordinateType.TRAIN_51 || !entity.isTroopWorldRight())
            {
                isShow = false;
            }

            return isShow;
        }
    }

    public class PlayerBattle
    {

        private Dictionary<Troop, bool> enemyPlayers;
        private Dictionary<Troop, bool> allies;
        //根据攻击方找被攻击方的表
        private Dictionary<Troop, Troop> marchBattleRelationAttackerAndTargetMap;
        
        //根据被攻击方找攻击方的表
        private Dictionary<Troop, List<Troop>> marchBattleRelationTargetAndAttackerMap;
        private MarchManager marchManager;
        //private Stack<List<long>> listPool;
        private ListPool<Troop> listPool;
        public PlayerBattle(MarchManager mgr)
        {
            marchManager = mgr;
            marchBattleRelationAttackerAndTargetMap = new Dictionary<Troop, Troop>(MarchManager.MarchEntityPoolNum);
            marchBattleRelationTargetAndAttackerMap = new Dictionary<Troop, List<Troop>>(MarchManager.MarchEntityPoolNum);
            allies = new Dictionary<Troop, bool>(MarchManager.MarchEntityPoolNum);
            enemyPlayers = new Dictionary<Troop, bool>(MarchManager.MarchEntityPoolNum);
            //listPool = new Stack<List<long>>(MarchManager.MarchEntityPoolNum);
            //for (int i = 0; i < MarchManager.MarchEntityPoolNum; i++)
            //{
            //    listPool.Push(new List<long>(20));
            //}
            listPool = new ListPool<Troop>(20,true,20,1,3);
        }

        public int GetPlayerAttackerCount(long tid,TargetCoordinateType type)
        {
            if (marchBattleRelationTargetAndAttackerMap.TryGetValue(new Troop(tid,type), out var list))
            {
                return list.Count;
            }
            return 0;
        }

        public void OnMarchAdded(RtsServerInfo serverInfo)
        {
            if (serverInfo.team == MarchHelper.TeamFriend)
                allies.Add(new Troop(serverInfo.tid,serverInfo.Type), true);
        }
        public void OnMarchRemoved(MarchEntity marchEntity)
        {
            allies.Remove(new Troop(marchEntity.MarchInfo.Uid,marchEntity.TargetCoordinateType));
            OnAttackRemoved(marchEntity.MarchInfo.Uid,marchEntity.TargetCoordinateType);
        }

        public void OnMarchChanged(RtsServerInfo serverInfo)
        {
            var status = serverInfo.marchStatus;
            var troop = new Troop(serverInfo.tid, serverInfo.Type);
            if (serverInfo.team != (int)MarchTeam.Ally && allies.ContainsKey(troop))
            {
                allies.Remove(troop);
            }
            if (status == MarchStatus.FIGHT_2 || status == MarchStatus.SIEGE_FIGHT_6)
            {
                OnAttackCreated(serverInfo.tid,serverInfo.Type, serverInfo.attackTargetId,serverInfo.attackTargetType);
            }
            else
            {
                OnAttackRemoved(serverInfo.tid,serverInfo.Type);
            }
        }
        
        public void OnMarchChanged(RtsMapMonster monster)
        {
            var lod3 = monster.lod3;
            var status = lod3.marchStatus;
            if (status == MarchStatus.FIGHT_2 || status == MarchStatus.SIEGE_FIGHT_6)
            {
                OnAttackCreated(lod3.npcUid, lod3.troopType,monster.lod3.attackTargetId,monster.lod3.attackTargetType);
            }
            else
            {
                OnAttackRemoved(lod3.npcUid,lod3.troopType);
            }
        }
        
        public void OnAttackCreated(long attackerId,TargetCoordinateType attackType, long beAttackerId,TargetCoordinateType targetType)
        {
            if (ArmyManager.IsDebug)
            {
                Debug.LogError(attackerId + " OnAttackCreated " + beAttackerId);
            }
            
            if (attackerId == 0 || beAttackerId == 0)
                return;
            
            var targetMarch = marchManager.GetMarchEntityByIdAndType(beAttackerId,targetType);
            if (targetMarch == null)//目标可能因为时序问题没有创建出来
            {
                MarchManager.Instance.RegistTargetIdFindSourceTroop(beAttackerId,targetType, attackerId,attackType);
                return;
            }
            var attacker = new Troop(attackerId,attackType);
            var beAttacker = new Troop(beAttackerId,targetType);
            if (!marchBattleRelationAttackerAndTargetMap.ContainsKey(attacker))
            {
                marchBattleRelationAttackerAndTargetMap.Add(attacker, beAttacker);
            }

            if (marchBattleRelationTargetAndAttackerMap.TryGetValue(beAttacker, out var attackerList))
            {
                if (!attackerList.Contains(attacker))
                {
                    attackerList.Add(attacker);
                    RoundFightPlayer.Inst.OnChangedEffect(beAttackerId,targetType);
                }
            }
            else
            {
                attackerList = listPool.GetItem();
                attackerList.Clear();
                marchBattleRelationTargetAndAttackerMap.Add(beAttacker, attackerList);
                attackerList.Add(attacker);
                RoundFightPlayer.Inst.OnChangedEffect(beAttackerId,targetType);
            }

            var isMyTroopsAttacking = IsMyTroopsAttacking(attackerId,attackType);
            var isEnemyTroopsAttackingMe = IsEnemyTroopsAttackingMe(beAttackerId, targetType);

            var isAllie = allies.ContainsKey(attacker) || allies.ContainsKey(beAttacker);

            // 和自己无关的不关心
            if (!isMyTroopsAttacking && !isEnemyTroopsAttackingMe && !isAllie)
            {
                var attackMarch = marchManager.GetMarchEntityByIdAndType(attackerId, attackType);
                if (attackMarch != null)
                {
                    attackMarch.Hud?.SetIsSelfAttacked(false);
                    attackMarch.Hud?.SetAttackSelf(false);
                }

                var beAttackMarch = marchManager.GetMarchEntityByIdAndType(beAttackerId, targetType);
                if (beAttackMarch != null)
                {
                    if (!IsTroopBeAttackedByMe(beAttackerId, targetType))
                    {
                        beAttackMarch.Hud?.SetAttackSelf(false); //有bug 新建立的会有问题
                        beAttackMarch.Hud?.SetIsSelfAttacked(false);
                    }
                }

                return;
            }


            MarchEntity march;
            if (isMyTroopsAttacking)
            {
                march = targetMarch;
                march.Hud?.SetIsSelfAttacked(true);
                if (march.Hud is MarchHud hud)
                    if (ArmyManager.IsDebug)
                    {
                        Debug.LogError("我被攻击的战斗 但攻击方没找到 " + attackerId + " " + beAttackerId);
                    }

                march = marchManager.GetMarchEntityByIdAndType(attackerId, attackType);
                if (march.Hud != null)
                {
                    march.Hud.SetAttackSelf(true);
                }
            }

            if (isEnemyTroopsAttackingMe)
            {
                march = marchManager.GetMarchEntityByIdAndType(attackerId, attackType);
                if (march != null)
                {
                    march.Hud?.SetAttackSelf(true);
                }
                else
                {
                    if (ArmyManager.IsDebug)
                    {
                        Debug.LogError("我在攻击的战斗 但攻击方没找到 " + attackerId + " " + beAttackerId);
                    }
                }
            }
        }

        private bool IsTroopBeAttackedByMe(long tid, TargetCoordinateType type)
        {
            var entity = marchManager.GetMarchEntityByIdAndType(tid, type);
            if (entity != null)
            {
                var attackTargetId = entity.RtsServerInfo.attackTargetId;
                var attackTargetType = entity.RtsServerInfo.attackTargetType;
                var attackTarget = marchManager.GetMarchEntityByIdAndType(attackTargetId, attackTargetType);
                if (attackTarget != null)
                {
                    return attackTarget.Team == (int) MarchTeam.Self;
                }
            }
            return false;
        }

        private bool IsMyTroopsAttacking(long tid,TargetCoordinateType type)
        {
            var entity = marchManager.GetMarchEntityByIdAndType(tid,type);
            if (entity == null)
            {
                return false;
            }

            bool isMyTroop = entity.RtsServerInfo.team == MarchHelper.TeamSelf;
            bool isMyAssembleTroop = false;
            if (entity.RtsServerInfo.isAssemblyLeader || entity.RtsServerInfo.Type == TargetCoordinateType.DEFENCE_ASSEMBLY_NPC_23 || entity.RtsServerInfo.Type == TargetCoordinateType.DEFENSE_ASSEMBLY_29)
            {
                isMyAssembleTroop = entity.RtsServerInfo.team == MarchHelper.TeamSelf ||
                                    entity.RtsServerInfo.team == MarchHelper.TeamFriend;
            }
            
            return isMyTroop || isMyAssembleTroop;
        }
        
        private bool IsEnemyTroopsAttackingMe(long beAttacker, TargetCoordinateType targetType)
        {
            if (targetType == TargetCoordinateType.ASSEMBLY_20) //集结部队
            {
                var entity = marchManager.GetMarchEntityByIdAndType(beAttacker,com.youzu.warh.protocol.TargetCoordinateType.ASSEMBLY_20);
                bool isMyAssembleTroop = false;
                if (entity!=null && (entity.RtsServerInfo.isAssemblyLeader))
                {
                    isMyAssembleTroop = entity.RtsServerInfo.team == MarchHelper.TeamSelf ||
                                        entity.RtsServerInfo.team == MarchHelper.TeamFriend;
                }
                return isMyAssembleTroop;
            }
            else if (targetType == TargetCoordinateType.DEFENCE_ASSEMBLY_NPC_23)
            {
                var entity = marchManager.GetMarchEntityByIdAndType(beAttacker,com.youzu.warh.protocol.TargetCoordinateType.DEFENCE_ASSEMBLY_NPC_23);
                if (entity != null)
                {
                    return entity.RtsServerInfo.team == MarchHelper.TeamSelf || entity.RtsServerInfo.team == MarchHelper.TeamFriend;
                }
                return false;
            }
            else if (targetType == TargetCoordinateType.DEFENSE_ASSEMBLY_29)
            {
                var entity = marchManager.GetMarchEntityByIdAndType(beAttacker, com.youzu.warh.protocol.TargetCoordinateType.DEFENSE_ASSEMBLY_29);
                if (entity != null)
                {
                    return entity.RtsServerInfo.team == MarchHelper.TeamSelf || entity.RtsServerInfo.team == MarchHelper.TeamFriend;
                }
                return false;
            }
            else
            {
                var entity = marchManager.GetMarchEntityByIdAndType(beAttacker,targetType);
                if (entity == null)
                {
                    return false;
                }
                return entity.RtsServerInfo.team == MarchHelper.TeamSelf;
            }
        }

        public bool IsSelfAttack(long id,TargetCoordinateType type)
        {
            if (marchBattleRelationTargetAndAttackerMap.TryGetValue(new Troop(id,type), out var attackerList))
            {
                if (attackerList != null)
                {
                    bool selfAttack = false;
                    foreach (var attacker in attackerList)
                    {
                        var attackerMarch = marchManager.GetMarchEntityByIdAndType(attacker.Uid,attacker.Type);
                        if (attackerMarch != null)
                        {
                            selfAttack = selfAttack || attackerMarch.Team == (int)MarchTeam.Self;
                        }
                    }
                    return selfAttack;
                }
                else
                {
                    return false;
                }
            }

            return false;
        }
        public void OnAttackRemoved(long removedId,TargetCoordinateType type)
        {
            if (ArmyManager.IsDebug)
            {
                Debug.LogError(removedId + " OnAttackRemoved");
            }
            var removedTroop = new Troop(removedId,type);
            Troop beAttacker;
            if (!marchBattleRelationAttackerAndTargetMap.TryGetValue(removedTroop, out beAttacker))
                return;

            if (marchBattleRelationTargetAndAttackerMap.TryGetValue(beAttacker, out var attackerList))
            {
                if (attackerList.Contains(removedTroop))
                {
                    attackerList.Remove(removedTroop);
                }
            }

            marchBattleRelationAttackerAndTargetMap.Remove(removedTroop);
            if (marchBattleRelationTargetAndAttackerMap.ContainsKey(removedTroop))
            {
                var list = marchBattleRelationTargetAndAttackerMap[removedTroop];
                list.Clear();
                listPool.RecoverItem(list);
                marchBattleRelationTargetAndAttackerMap.Remove(removedTroop);
            }

            RoundFightPlayer.Inst.OnChangedEffect(beAttacker.Uid,beAttacker.Type);
            bool isSelfTeam = false;
            var removedMarch = marchManager.GetMarchEntityByIdAndType(removedId,type);
            if (removedMarch != null)
            {
                marchManager.SetTroopHudAlpha(new Troop(removedId,type), false);
            }

            if (removedMarch!=null)
            {
                if (removedMarch.Hud is MarchHud removedMarchHud)
                {
                    if (removedMarchHud.IsSelfAttacking)
                    {
                        removedMarchHud.IsSelfAttacking = false;
                    }
                }
            }

            //自己只管自己的，不去动别人的
            /*var march = marchManager.GetMarchEntityById(removeRelationMarchId);
            if (march!=null)
            {
                if (march.Hud!=null)
                {
                    march.Hud.SetIsSelfAttacked(false);
                    bool isAttackSelf = march.MarchInfo.BattleTargetId == removedId;
                    if (isAttackSelf)
                    {
                        if (isSelfTeam)
                        {
                            march.Hud.SetAttackSelf(false);
                        }
                    }
                }
            }*/
        }

        internal List<Troop> GetAllRelationTroop(Troop target)
        {
            List<Troop> list = new List<Troop>();
            if (marchBattleRelationAttackerAndTargetMap.TryGetValue(target, out var beAttackId))
            {
                list.Add(beAttackId);
            }

            if (marchBattleRelationTargetAndAttackerMap.TryGetValue(target, out var attackList))
            {
                list.AddRange(attackList);
            }
            list.Add(target);
            return list;
        }

    }
}
